Compare commits

..

72 Commits

Author SHA1 Message Date
Jan Vidar Krey
f1cd5bb535 Branched off 0.2.x stable branch (0.2.x-stable) 2009-05-29 14:43:41 +02:00
Jan Vidar Krey
caec28f63f Warn on bad UTF-8 in the configuration file. 2009-05-16 12:48:17 +02:00
Jan Vidar Krey
5ea5efb875 Smome user manager functions did not have the uman_ prefix. 2009-05-16 12:42:30 +02:00
Jan Vidar Krey
326fcc467c Moved the update_user_info code into user_update_info 2009-05-16 12:32:48 +02:00
Jan Vidar Krey
078470ce64 Minor cleanup 2009-05-16 12:25:28 +02:00
Jan Vidar Krey
82ac450b4b Fixed further memory leaks in autotests. 2009-05-16 04:03:00 +02:00
Jan Vidar Krey
b4f24b21f9 Document bandwidth optimization potential. 2009-05-16 03:45:05 +02:00
Jan Vidar Krey
968266b22f Fix memory leaks. 2009-05-16 03:44:51 +02:00
Jan Vidar Krey
548867de10 Removed ADC_UDP_OPERATION code as it is not used or needed. on_kick is also gone. 2009-05-16 03:14:20 +02:00
Jan Vidar Krey
953db2dcbc Fixed some autotest memory leaks. 2009-05-16 03:06:14 +02:00
Jan Vidar Krey
6e4ac1355f Fix autotest crashers. 2009-05-16 02:33:43 +02:00
Jan Vidar Krey
604364ffa5 Fixed various code deprecations
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-05-15 18:45:26 +02:00
Jan Vidar Krey
6cc1af5671 Disable code to prevent warnings. 2009-05-15 16:52:55 +02:00
Jan Vidar Krey
15e2053699 Fix #28 - Request: +/! characters for command handling (FleetCommand) 2009-05-15 16:52:04 +02:00
Jan Vidar Krey
df1e832a3c Started working on a red-black tree implementation, need to speed up
certain operations, such as SID to user lookups, and nick to user.
2009-05-01 17:07:38 +02:00
Jan Vidar Krey
4c4cb4fb36 Dont allow clients that do not support BASE
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-04-13 05:31:41 +02:00
Jan Vidar Krey
e49f9d4d30 Added kick support
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-04-09 00:48:00 +02:00
Jan Vidar Krey
e73a931243 Ensure we do not allow update of certain elements.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-27 11:12:50 +01:00
Jan Vidar Krey
ae017af758 Log version and method of libevent()
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-24 23:32:39 +01:00
Jan Vidar Krey
7a02f92a4c Cleanup after creating debian packages.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-24 23:16:09 +01:00
Jan Vidar Krey
adeebb92a0 Added manual page. 2009-03-24 23:14:04 +01:00
Jan Vidar Krey
26f1864c1f Don't crash if one specify '-S' or '-s' and an invalid configuration file. 2009-03-24 23:10:51 +01:00
Jan Vidar Krey
c14fa3c3a9 Added more debugging info for mainloop bug #16 - In addition to small fixes to it.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-24 22:06:26 +01:00
Jan Vidar Krey
dfd2191103 White space cleanups. 2009-03-24 18:39:39 +01:00
Jan Vidar Krey
0042344054 Better dpkg system. 2009-03-24 18:38:59 +01:00
Jan Vidar Krey
8af965c0ca Fixed utf8 parse issue.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-24 00:21:38 +01:00
Jan Vidar Krey
b3d3dcdb44 Actually do upload.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 23:45:39 +01:00
Jan Vidar Krey
cb6190c5b4 FreeBSD fix.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 23:39:34 +01:00
Jan Vidar Krey
82ad62602d 0.2.8 release candidate.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 23:36:29 +01:00
Jan Vidar Krey
6d34bdd7e2 Added upload script.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 23:32:32 +01:00
Jan Vidar Krey
c2832e59c0 Added build script setup for easy publishing...
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 23:30:51 +01:00
Jan Vidar Krey
cf23c82c16 Added upload support.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 23:02:59 +01:00
Jan Vidar Krey
8bf0fd424a Added upload support. 2009-03-23 23:02:52 +01:00
Jan Vidar Krey
8f8284eb29 Ensure we build source .zip file. 2009-03-23 22:54:59 +01:00
Jan Vidar Krey
015c3368bd Added new script for building sources only.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 22:51:53 +01:00
Jan Vidar Krey
9186b441aa Minor build system tweaks.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 22:47:08 +01:00
Jan Vidar Krey
74af392e80 Stop in case of error.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 22:40:15 +01:00
Jan Vidar Krey
3a270564d2 Fixed up admin scripts.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 22:36:45 +01:00
Jan Vidar Krey
f0938e8afa Fixed up build scripts somewhat. 2009-03-23 22:33:45 +01:00
Jan Vidar Krey
156c137237 Autotest for bug #12
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 21:55:24 +01:00
Jan Vidar Krey
7aeb8651ba Fix bug #12: asserts in adc_msg_parse -> enabled strict utf8 parsing.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 21:47:05 +01:00
Jan Vidar Krey
ab4eb6db3d Document 0.2.8 changes. 2009-03-23 16:51:06 +01:00
Jan Vidar Krey
13a8700554 Make sure logs do not output configured messages, but rather code names.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 15:47:54 +01:00
Jan Vidar Krey
5d5dda2f9b Always obtain IP address during accept(), and not do it later as a call to getsockname().
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 15:05:27 +01:00
Jan Vidar Krey
95b741bb5e More message tests. 2009-03-23 14:58:15 +01:00
Jan Vidar Krey
90abf64e3a Do explicit logging in src/message.c 2009-03-23 08:18:25 +01:00
Jan Vidar Krey
e9915df87c remove timezone from logs, as it screws up on windows.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-21 04:11:14 +01:00
Jan Vidar Krey
408829e330 Another 0.2.7 candidate.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-21 03:59:12 +01:00
Jan Vidar Krey
1a1b5bdb38 Fixed nasty crash if a user sends a very large command to the hub.
Will overwrite heap memory.
Thanks to Toast who found this bug.

Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-21 02:58:53 +01:00
Jan Vidar Krey
abedec692a 0.2.7 release candidate
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 19:12:18 +01:00
Jan Vidar Krey
7738baf38e Log configuration reloads.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 19:09:55 +01:00
Jan Vidar Krey
3c4c52d0f9 Log configuration reloads.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 19:08:24 +01:00
Jan Vidar Krey
76588fb1bd Don't print OK or ERROR when dumping config.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 19:05:25 +01:00
Jan Vidar Krey
f9e95ec582 Minor cleanups
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 19:02:32 +01:00
Jan Vidar Krey
7985d4fed0 Cleanup credentials to string handling
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 18:54:05 +01:00
Jan Vidar Krey
77343d3c21 Remove duplicate access_denied checks.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 18:38:42 +01:00
Jan Vidar Krey
f8d5b72a89 Cleanup command list, automatically generate help list depending on user credentials. 2009-03-20 18:37:38 +01:00
Jan Vidar Krey
cf2994b570 Fix whitespace 2009-03-20 18:37:05 +01:00
Jan Vidar Krey
7a9d40d8dd Fix autotests for event queue.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 17:42:29 +01:00
Jan Vidar Krey
b1f84b5b4a Cleanup logging.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 17:40:50 +01:00
Jan Vidar Krey
998c6c36ce Fix indentation 2009-03-20 16:40:59 +01:00
Jan Vidar Krey
4112b8111a Fix problems with clients sending multiple INF messages during the login stage. Only the first one will be checked. 2009-03-20 16:40:34 +01:00
Jan Vidar Krey
1929f2fae7 Fix bug #9 - net_get_peer_address() failure on CentOS/Xen configurations.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 15:07:52 +01:00
Jan Vidar Krey
77e41371b5 Ensure we install to /usr/local by default.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-19 20:02:03 +01:00
Jan Vidar Krey
0266c8bb9c Libevent fixes, and memory leak fix.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-19 17:57:04 +01:00
Jan Vidar Krey
5e3eabb677 Fix help message typo
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-19 01:30:46 +01:00
Jan Vidar Krey
669ab14022 Minor cleanups and stack reduction.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-19 01:27:34 +01:00
Jan Vidar Krey
1d491055c5 Do not use event_loopexit with new event loop.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-19 01:13:02 +01:00
Jan Vidar Krey
08351ea8e7 Merge branch 'event_queue_work' 2009-03-19 01:08:57 +01:00
Jan Vidar Krey
e2ac690164 Reindented code. 2009-03-19 01:01:36 +01:00
Jan Vidar Krey
3bb563b432 Cleaned up command system somewhat. Added admin commands for reload and shutdown. 2009-03-19 00:55:11 +01:00
Jan Vidar Krey
e10582fec2 Cleaned up command system slightly.
Added admin commands for reload and shutdown.
2009-03-19 00:53:44 +01:00
58 changed files with 1292 additions and 1185 deletions

View File

@@ -1,4 +1,19 @@
0.2.8:
- Fix bug #13: getsockname() failure, use sockaddr from accept() instead.
- Fix bug #10: Improve logging, ensure logs are machine readable.
- Fix bug #12: asserts in adc_msg_parse -> enabled strict utf8 parsing.
0.2.7: 0.2.7:
- Fixed a nasty crash (bug #11), Thanks Toast for finding it.
- Fix bug #9 - net_get_peer_address() failure on CentOS/Xen configurations.
- Write a log message if an operator reloads the config file.
- Don't print OK or ERROR when using '-s' or '-S' show the configuration.
- Cleanup credential string handling
- Made sure "!help" only display accessible commands.
- Cleanup in-hub command parsing
- Fix a possible crash if multiple INF messages are sent during login.
- Rewrote the mainloop to not use a timer.
0.2.6: 0.2.6:

View File

@@ -32,7 +32,7 @@ BIN_EXT ?= .exe
else else
DESTDIR ?= / DESTDIR ?= /
UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub
UHUB_PREFIX ?= $(DESTDIR)/usr/ UHUB_PREFIX ?= $(DESTDIR)/usr/local
CFLAGS += -I/usr/local/include CFLAGS += -I/usr/local/include
LDFLAGS += -L/usr/local/lib LDFLAGS += -L/usr/local/lib
BIN_EXT ?= BIN_EXT ?=
@@ -144,6 +144,7 @@ libuhub_SOURCES := \
src/misc.c \ src/misc.c \
src/netevent.c \ src/netevent.c \
src/network.c \ src/network.c \
src/rbtree.c \
src/route.c \ src/route.c \
src/sid.c \ src/sid.c \
src/tiger.c \ src/tiger.c \
@@ -171,6 +172,7 @@ uhub_HEADERS := \
src/misc.h \ src/misc.h \
src/netevent.h \ src/netevent.h \
src/network.h \ src/network.h \
src/rbtree.h \
src/route.h \ src/route.h \
src/sid.h \ src/sid.h \
src/tiger.h \ src/tiger.h \
@@ -187,6 +189,7 @@ autotest_SOURCES := \
autotest/test_hub.tcc \ autotest/test_hub.tcc \
autotest/test_misc.tcc \ autotest/test_misc.tcc \
autotest/test_tiger.tcc \ autotest/test_tiger.tcc \
autotest/test_usermanager.tcc \
autotest/test_eventqueue.tcc autotest/test_eventqueue.tcc
autotest_OBJECTS = autotest.o autotest_OBJECTS = autotest.o

View File

@@ -6,25 +6,30 @@ else
HOST_MACHINE=`uname -m | tr [:upper:] [:lower:] | sed s/i686/i386/ | sed s/x86_64/amd64/ | sed s/ppc64/powerpc/` HOST_MACHINE=`uname -m | tr [:upper:] [:lower:] | sed s/i686/i386/ | sed s/x86_64/amd64/ | sed s/ppc64/powerpc/`
fi fi
BINSUFFIX=
MAKEARGS=
MAKE=make
WANTZIP=0
if [ "${HOST_SYSTEM}" = "mingw32_nt-5.1" ]; then if [ "${HOST_SYSTEM}" = "mingw32_nt-5.1" ]; then
HOST_SYSTEM=win32 HOST_SYSTEM=win32
BINARY=uhub.exe BINSUFFIX=.exe
WANTZIP=1 WANTZIP=1
else MAKEARGS="USE_BIGENDIAN=NO"
WANTZIP=0
BINARY=uhub
fi fi
BINARY=uhub${BINSUFFIX}
if [ "${HOST_SYSTEM}" = "freebsd" ]; then
MAKE=gmake
fi
VERSION=`grep define\ VERSION version.h | cut -f 3 -d " " | tr -d [=\"=]` VERSION=`grep define\ VERSION version.h | cut -f 3 -d " " | tr -d [=\"=]`
SNAPSHOT=`date '+%Y%m%d'` SNAPSHOT=`date '+%Y%m%d'`
PACKAGE=uhub-${VERSION} PACKAGE=uhub-${VERSION}
PACKAGE_SRC=${PACKAGE}-src PACKAGE_SRC=${PACKAGE}-src
PACKAGE_BIN=${PACKAGE}-${HOST_SYSTEM}-${HOST_MACHINE} PACKAGE_BIN=${PACKAGE}-${HOST_SYSTEM}-${HOST_MACHINE}
ARCHIVE='build-archive:~/www/downloads/uhub/'
URL_ARCHIVE='build-archive:~/uhub/'
URL_PUBLISH='domeneshop:~/www/downloads/uhub/'
URL_SNAPSHOT='domeneshop:~/www/downloads/uhub/snapshots/'
function export_source_directory function export_source_directory
{ {
@@ -51,45 +56,85 @@ function package_zips
gzip -c -9 $1.tar > $1.tar.gz gzip -c -9 $1.tar > $1.tar.gz
bzip2 -c -9 $1.tar > $1.tar.bz2 bzip2 -c -9 $1.tar > $1.tar.bz2
rm -f $1.tar rm -f $1.tar
if [ $WANTZIP -eq 1 ]; then
zip -q -9 -r $1.zip $2 zip -q -9 -r $1.zip $2
fi
} }
function export_sources function export_sources
{ {
if [ ! -d ${PACKAGE} ]; then
export_source_directory export_source_directory
make autotest.c && cp autotest.c ${PACKAGE}/autotest.c fi
rm -Rf ${PACKAGE}/admin
cd ${PACKAGE}
${MAKE} ${MAKEARGS} autotest.c
cd ..
if [ ! -f ${PACKAGE}/autotest.c ]; then
echo "Unable to create autotest.c, aborting..."
exit 1
fi
rm -Rf ${PACKAGE}/admin
package_zips ${PACKAGE_SRC} ${PACKAGE} package_zips ${PACKAGE_SRC} ${PACKAGE}
rm -Rf ${PACKAGE}; rm -Rf ${PACKAGE};
cp ChangeLog ChangeLog-${VERSION} cp ChangeLog ChangeLog-${VERSION}
} }
function build_binaries
{
if [ ! -d ${PACKAGE} ]; then
export_source_directory
fi
cd ${PACKAGE}
${MAKE} ${MAKEARGS} RELEASE=YES
cd ..
if [ ! -x ${PACKAGE}/${BINARY} ]; then
echo "Build failed, no binary found..."
exit 1
fi
}
function export_binaries function export_binaries
{ {
export_source_directory build_binaries
rm -Rf ${PACKAGE}/admin rm -Rf ${PACKAGE}/admin
rm -Rf ${PACKAGE}/autotest rm -Rf ${PACKAGE}/autotest
rm -Rf ${PACKAGE}/src rm -Rf ${PACKAGE}/src
rm -Rf ${PACKAGE}/debian
rm -f ${PACKAGE}/autotest.c rm -f ${PACKAGE}/autotest.c
rm -f ${PACKAGE}/*akefile rm -f ${PACKAGE}/*akefile
rm -f ${PACKAGE}/version.h rm -f ${PACKAGE}/version.h
rm -f ${PACKAGE}/doc/Doxyfile rm -f ${PACKAGE}/doc/Doxyfile
rm -f ${PACKAGE}/doc/uhub.dot rm -f ${PACKAGE}/doc/uhub.dot
rm -f ${PACKAGE}/libuhub*
make
if [ -x ${BINARY} ]; then
cp ${BINARY} ${PACKAGE}
else
echo "No binary found!"
exit 1
fi
package_zips ${PACKAGE_BIN} ${PACKAGE} package_zips ${PACKAGE_BIN} ${PACKAGE}
rm -Rf ${PACKAGE}
}
rm -Rf ${PACKAGE}; function upload_pkg
{
if [ -f $1 ]; then
scp $1 ${ARCHIVE}
fi
}
function upload_packages
{
upload_pkg ${PACKAGE_SRC}.tar.gz
upload_pkg ${PACKAGE_SRC}.tar.bz2
upload_pkg ${PACKAGE_SRC}.zip
upload_pkg ChangeLog-${VERSION}
upload_pkg ${PACKAGE_BIN}.tar.gz
upload_pkg ${PACKAGE_BIN}.tar.bz2
upload_pkg ${PACKAGE_BIN}.zip
} }

3
admin/export.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
. admin/common.sh
export_source_directory

95
admin/make_pkg_deb.sh Executable file
View File

@@ -0,0 +1,95 @@
#!/bin/sh
. admin/common.sh
export_source_directory
build_binaries
DEB_REVISION=1
if [ -d deb ]; then
rm -Rf deb
fi
mkdir -p \
deb/DEBIAN \
deb/usr/bin \
deb/usr/share/man/man1/ \
deb/usr/share/doc/uhub \
deb/etc/uhub \
|| exit 1
find deb -type d | xargs chmod 755
# Copy binaries...
cp ${PACKAGE}/${BINARY} deb/usr/bin
strip deb/usr/bin/${BINARY}
# Copy configuration files...
cp ${PACKAGE}/doc/uhub.conf deb/etc/uhub
cp ${PACKAGE}/doc/users.conf deb/etc/uhub
echo "Welcome to uHub" > deb/etc/uhub/motd.txt
# Copy other files
cp ${PACKAGE}/README deb/usr/share/doc/uhub
cp ${PACKAGE}/AUTHORS deb/usr/share/doc/uhub
gzip -c --best < ${PACKAGE}/ChangeLog > deb/usr/share/doc/uhub/changelog.gz
gzip -c --best < ${PACKAGE}/doc/uhub.1 > deb/usr/share/man/man1/uhub.1.gz
cat > deb/usr/share/doc/uhub/copyright <<EOF
uHub - a high performance hub for the ADC peer-to-peer network
Copyright (C) 2007-2009 Jan Vidar Krey <janvidar@extatic.org>
uHub is free and open source software, licensed under the
GNU General Public License version 3.
For details, see /usr/share/common-licenses/GPL-3
EOF
gzip -c --best > deb/usr/share/doc/uhub/changelog.Debian.gz <<EOF
uhub (${VERSION}) stable; urgency=low
* See changelog.gz for details.
-- Jan Vidar Krey <janvidar@extatic.org> `date -R`
EOF
### Write control files
cd deb
echo "/etc/uhub/uhub.conf" > DEBIAN/conffiles
echo "/etc/uhub/users.conf" >> DEBIAN/conffiles
echo "/etc/uhub/motd.txt" >> DEBIAN/conffiles
md5sum `find usr -type f` > DEBIAN/md5sums
INSTALL_SIZE=`du -s | cut -f 1`
cat > DEBIAN/control <<EOF
Package: uhub
Version: ${VERSION}-${DEB_REVISION}
Architecture: ${HOST_MACHINE}
Maintainer: Jan Vidar Krey <janvidar@extatic.org>
Installed-Size: ${INSTALL_SIZE}
Depends: libc6 (>= 2.7-1), libevent1 (>= 1.3e-1)
Section: net
Priority: optional
Description: a high performance hub for the ADC peer-to-peer network
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.
.
Homepage: http://www.extatic.org/uhub/
EOF
cd ..
### Create deb file
fakeroot dpkg-deb --build deb
mv deb.deb uhub_${VERSION}-${DEB_REVISION}_${HOST_MACHINE}.deb
### Check for errors
lintian uhub_${VERSION}-${DEB_REVISION}_${HOST_MACHINE}.deb
### Cleanup
rm -Rf deb
rm -Rf ${PACKAGE}

View File

@@ -1,11 +0,0 @@
#!/bin/bash
# set -x
ME=`dirname $0`
. ${ME}/common.sh
# Git Export
export_sources
export_binaries

3
admin/release_binaries.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
. admin/common.sh
export_binaries

4
admin/release_sources.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
. admin/common.sh
WANTZIP=1
export_sources

26
admin/setup_archive.sh Executable file
View File

@@ -0,0 +1,26 @@
#!/bin/bash
PUB="${HOME}/.ssh/id_rsa.pub"
CFG="${HOME}/.ssh/config"
if [ ! "`grep build-archive ${CFG}`" ]; then
echo "Updating ssh config (${CFG})..."
cat >> ${CFG} <<EOF
Host build-archive
ForwardX11 no
HostName login.domeneshop.no
User extatic
EOF
else
echo "ssh config seems OK (${CFG})"
fi
if [ ! -f ${PUB} ]; then
echo "No id_rsa.pub - run ssh-keygen"
exit 1
fi
echo "Copying public key (${PUB})..."
cat ${PUB} | ssh build-archive "cat >> .ssh/authorized_keys"

3
admin/upload.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
. admin/common.sh
upload_packages

View File

@@ -2,7 +2,6 @@
static struct event_queue* eq; static struct event_queue* eq;
static int eq_val; static int eq_val;
struct event* libevent_handle;
static void eq_callback(void* callback_data, struct event_data* event_data) static void eq_callback(void* callback_data, struct event_data* event_data)
{ {
@@ -17,8 +16,6 @@ EXO_TEST(eventqueue_init_1, {
EXO_TEST(eventqueue_init_2, { EXO_TEST(eventqueue_init_2, {
/* hack */ /* hack */
libevent_handle = eq->event;
eq->event = 0;
return eq->callback_data == &eq_val && eq->callback == eq_callback && eq->q1 && eq->q2 && !eq->locked; return eq->callback_data == &eq_val && eq->callback == eq_callback && eq->q1 && eq->q2 && !eq->locked;
}); });
@@ -81,7 +78,6 @@ EXO_TEST(eventqueue_size_4, {
}); });
EXO_TEST(eventqueue_shutdown_1, { EXO_TEST(eventqueue_shutdown_1, {
eq->event = libevent_handle;
event_queue_shutdown(eq); event_queue_shutdown(eq);
return 1; return 1;
}); });

View File

@@ -8,7 +8,7 @@
static struct user* inf_user = 0; static struct user* inf_user = 0;
static struct hub_info* inf_hub = 0; static struct hub_info* inf_hub = 0;
extern int hub_handle_info_login(struct user* user, struct adc_message* cmd); extern int hub_handle_info_login(struct hub_info* hub, struct user* user, struct adc_message* cmd);
static void inf_create_hub() static void inf_create_hub()
{ {
@@ -27,6 +27,13 @@ static void inf_create_hub()
static void inf_destroy_hub() static void inf_destroy_hub()
{ {
/* FIXME */ /* FIXME */
list_destroy(inf_hub->users->list);
acl_shutdown(inf_hub->acl);
free_config(inf_hub->config);
hub_free(inf_hub->users);
hub_free(inf_hub->acl);
hub_free(inf_hub->config);
hub_free(inf_hub);
} }
@@ -36,7 +43,6 @@ static void inf_create_user()
inf_user = (struct user*) hub_malloc_zero(sizeof(struct user)); inf_user = (struct user*) hub_malloc_zero(sizeof(struct user));
inf_user->id.sid = 1; inf_user->id.sid = 1;
inf_user->sd = -1; inf_user->sd = -1;
inf_user->hub = inf_hub;
inf_user->limits.upload_slots = 1; inf_user->limits.upload_slots = 1;
} }
@@ -55,13 +61,13 @@ EXO_TEST(inf_create_setup,
}); });
/* FIXME: MEMORY LEAK - Need to fix hub_handle_info_login */
#define CHECK_INF(MSG, EXPECT) \ #define CHECK_INF(MSG, EXPECT) \
struct adc_message* msg = adc_msg_parse_verify(inf_user, MSG, strlen(MSG)); \ struct adc_message* msg = adc_msg_parse_verify(inf_user, MSG, strlen(MSG)); \
int ok = hub_handle_info_login(inf_user, msg); \ int ok = hub_handle_info_login(inf_hub, inf_user, msg); /* FIXME: MEMORY LEAK */ \
adc_msg_free(msg); \ adc_msg_free(msg); \
if (ok != EXPECT) \ if (ok == EXPECT) \
printf("Expected %d, got %d\n", EXPECT, ok); \ user_set_info(inf_user, 0); \
return ok == EXPECT; return ok == EXPECT;
@@ -106,7 +112,7 @@ EXO_TEST(inf_nick_10, {
struct adc_message* msg = adc_msg_parse_verify(inf_user, line, strlen(line)); struct adc_message* msg = adc_msg_parse_verify(inf_user, line, strlen(line));
adc_msg_add_named_argument(msg, "NI", nick); adc_msg_add_named_argument(msg, "NI", nick);
int ok = hub_handle_info_login(inf_user, msg); int ok = hub_handle_info_login(inf_hub, inf_user, msg);
adc_msg_free(msg); adc_msg_free(msg);
if (ok != status_msg_inf_error_nick_not_utf8) if (ok != status_msg_inf_error_nick_not_utf8)
printf("Expected %d, got %d\n", status_msg_inf_error_nick_not_utf8, ok); printf("Expected %d, got %d\n", status_msg_inf_error_nick_not_utf8, ok);

View File

@@ -17,6 +17,11 @@ static void create_test_user()
g_user->id.sid = 1; g_user->id.sid = 1;
} }
EXO_TEST(adc_message_first, {
create_test_user();
return g_user != 0;
});
EXO_TEST(adc_message_parse_1, { EXO_TEST(adc_message_parse_1, {
struct adc_message* msg = adc_msg_create("IMSG Hello\\sWorld!"); struct adc_message* msg = adc_msg_create("IMSG Hello\\sWorld!");
int ok = msg != NULL; int ok = msg != NULL;
@@ -30,7 +35,6 @@ EXO_TEST(adc_message_parse_2, {
}); });
EXO_TEST(adc_message_parse_3, { EXO_TEST(adc_message_parse_3, {
create_test_user();
struct adc_message* msg = adc_msg_parse_verify(g_user, "BMSG AAAB Hello\\sWorld!", 23); struct adc_message* msg = adc_msg_parse_verify(g_user, "BMSG AAAB Hello\\sWorld!", 23);
int ok = msg != NULL; int ok = msg != NULL;
adc_msg_free(msg); adc_msg_free(msg);
@@ -144,12 +148,29 @@ EXO_TEST(adc_message_parse_20, {
return ok; return ok;
}); });
EXO_TEST(adc_message_parse_21, { EXO_TEST(adc_message_parse_21, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "EMSG AAAC AAAB Hello\\sthere!\n", 29); struct adc_message* msg = adc_msg_parse_verify(g_user, "EMSG AAAC AAAB Hello\\sthere!\n", 29);
return msg == NULL; return msg == NULL;
}); });
EXO_TEST(adc_message_parse_22, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "\n", 0);
return msg == NULL;
});
EXO_TEST(adc_message_parse_23, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "\r\n", 1);
return msg == NULL;
});
EXO_TEST(adc_message_parse_24, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "EMSG AAAC\0AAAB Hello\\sthere!\n", 29);
return msg == NULL;
});
EXO_TEST(adc_message_add_arg_1, { EXO_TEST(adc_message_add_arg_1, {
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXwtf?"); adc_msg_add_argument(msg, "XXwtf?");
@@ -491,13 +512,22 @@ EXO_TEST(adc_message_update_3, {
return updater2 != NULL; return updater2 != NULL;
}); });
extern void update_user_info(struct user* u, struct adc_message* cmd);
EXO_TEST(adc_message_update_4, { EXO_TEST(adc_message_update_4, {
update_user_info(g_user, updater2); user_update_info(g_user, updater2);
return strlen(g_user->info->cache) == 159; return strlen(g_user->info->cache) == 159;
}); });
EXO_TEST(adc_message_update_4_cleanup, {
adc_msg_free(updater1);
updater1 = 0;
adc_msg_free(updater2);
updater2 = 0;
adc_msg_free(g_user->info);
g_user->info = 0;
return 1;
});
EXO_TEST(adc_message_empty_1, { EXO_TEST(adc_message_empty_1, {
struct adc_message* msg = adc_msg_parse_verify(g_user, test_string2, strlen(test_string2)); struct adc_message* msg = adc_msg_parse_verify(g_user, test_string2, strlen(test_string2));
int ok = adc_msg_is_empty(msg) == 0; int ok = adc_msg_is_empty(msg) == 0;
@@ -519,3 +549,10 @@ EXO_TEST(adc_message_empty_3, {
return ok; return ok;
}); });
EXO_TEST(adc_message_last, {
hub_free(g_user);
g_user = 0;
return g_user == 0;
});

View File

@@ -100,4 +100,12 @@ EXO_TEST(utf8_valid_3, { return is_valid_utf8("0123456789"); });
EXO_TEST(utf8_valid_4, { return is_valid_utf8( (char[]) { 0x65, 0x00} ); }); EXO_TEST(utf8_valid_4, { return is_valid_utf8( (char[]) { 0x65, 0x00} ); });
EXO_TEST(utf8_valid_5, { return !is_valid_utf8( (char[]) { 0xD8, 0x00} ); }); EXO_TEST(utf8_valid_5, { return !is_valid_utf8( (char[]) { 0xD8, 0x00} ); });
EXO_TEST(utf8_valid_6, { return is_valid_utf8( (char[]) { 0x24, 0x00} ); });
EXO_TEST(utf8_valid_7, { return !is_valid_utf8( (char[]) { 0xC2, 0x24, 0x00} ); });
EXO_TEST(utf8_valid_8, { return is_valid_utf8( (char[]) { 0xC2, 0xA2, 0x00} ); });
EXO_TEST(utf8_valid_9, { return is_valid_utf8( (char[]) { 0xE2, 0x82, 0xAC, 0x00} ); });
EXO_TEST(utf8_valid_10, { return !is_valid_utf8( (char[]) { 0xC2, 0x32, 0x00} ); });
EXO_TEST(utf8_valid_11, { return !is_valid_utf8( (char[]) { 0xE2, 0x82, 0x32, 0x00} ); });
EXO_TEST(utf8_valid_12, { return !is_valid_utf8( (char[]) { 0xE2, 0x32, 0x82, 0x00} ); });

5
debian/changelog vendored
View File

@@ -1,5 +0,0 @@
uhub (0.2.6-1) unstable; urgency=low
* Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
-- Jan Vidar Krey <janvidar@extatic.org> Tue, 17 Mar 2009 00:38:12 +0100

1
debian/compat vendored
View File

@@ -1 +0,0 @@
7

3
debian/conffiles vendored
View File

@@ -1,3 +0,0 @@
etc/uhub/uhub.conf
etc/uhub/users.conf
etc/uhub/motd.txt

15
debian/control vendored
View File

@@ -1,15 +0,0 @@
Source: uhub
Section: net
Priority: extra
Maintainer: Jan Vidar Krey <janvidar@extatic.org>
Build-Depends: debhelper (>= 7)
Standards-Version: 3.8.1
Homepage: http://www.extatic.org/uhub/
Package: uhub
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
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.
uHub uses the ADC protocol, and is compatible with DC++, jUCy and other ADC clients.

9
debian/copyright vendored
View File

@@ -1,9 +0,0 @@
Copyright:
Copyright (C) 2008-2009 Jan Vidar Krey <janvidar@extatic.org>
License:
Licensed under the GPL version 3,
see `/usr/share/common-licenses/GPL-3'.

1
debian/dirs vendored
View File

@@ -1 +0,0 @@
usr/bin

3
debian/docs vendored
View File

@@ -1,3 +0,0 @@
BUGS
README
AUTHORS

1
debian/files vendored
View File

@@ -1 +0,0 @@
uhub_0.2.6-1_amd64.deb net extra

157
debian/init.d vendored
View File

@@ -1,157 +0,0 @@
#! /bin/sh
#
# skeleton example file to build /etc/init.d/ scripts.
# This file should be used to construct scripts for /etc/init.d.
#
# Written by Miquel van Smoorenburg <miquels@cistron.nl>.
# Modified for Debian
# by Ian Murdock <imurdock@gnu.ai.mit.edu>.
# Further changes by Javier Fernandez-Sanguino <jfs@debian.org>
#
# Version: @(#)skeleton 1.9 26-Feb-2001 miquels@cistron.nl
#
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/bin/uhub
NAME=uhub
DESC=uhub
test -x $DAEMON || exit 0
LOGDIR=/var/log/uhub
PIDFILE=/var/run/$NAME.pid
DODTIME=1 # Time to wait for the server to die, in seconds
# If this value is set too low you might not
# let some servers to die gracefully and
# 'restart' will not work
# Include uhub defaults if available
if [ -f /etc/default/uhub ] ; then
. /etc/default/uhub
fi
set -e
running_pid()
{
# Check if a given process pid's cmdline matches a given name
pid=$1
name=$2
[ -z "$pid" ] && return 1
[ ! -d /proc/$pid ] && return 1
cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1 |cut -d : -f 1`
# Is this the expected child?
[ "$cmd" != "$name" ] && return 1
return 0
}
running()
{
# Check if the process is running looking at /proc
# (works for all users)
# No pidfile, probably no daemon present
[ ! -f "$PIDFILE" ] && return 1
# Obtain the pid and check it against the binary name
pid=`cat $PIDFILE`
running_pid $pid $DAEMON || return 1
return 0
}
force_stop() {
# Forcefully kill the process
[ ! -f "$PIDFILE" ] && return
if running ; then
kill -15 $pid
# Is it really dead?
[ -n "$DODTIME" ] && sleep "$DODTIME"s
if running ; then
kill -9 $pid
[ -n "$DODTIME" ] && sleep "$DODTIME"s
if running ; then
echo "Cannot kill $LABEL (pid=$pid)!"
exit 1
fi
fi
fi
rm -f $PIDFILE
return 0
}
case "$1" in
start)
echo -n "Starting $DESC: "
start-stop-daemon --start --quiet --pidfile $PIDFILE \
--exec $DAEMON -- $DAEMON_OPTS
if running ; then
echo "$NAME."
else
echo " ERROR."
fi
;;
stop)
echo -n "Stopping $DESC: "
start-stop-daemon --stop --quiet --pidfile $PIDFILE \
--exec $DAEMON
echo "$NAME."
;;
force-stop)
echo -n "Forcefully stopping $DESC: "
force_stop
if ! running ; then
echo "$NAME."
else
echo " ERROR."
fi
;;
reload)
#
# If the daemon can reload its config files on the fly
# for example by sending it SIGHUP, do it here.
#
# If the daemon responds to changes in its config file
# directly anyway, make this a do-nothing entry.
#
echo "Reloading $DESC configuration files."
start-stop-daemon --stop --signal 1 --quiet --pidfile \
/var/run/$NAME.pid --exec $DAEMON
#;;
force-reload)
#
# If the "reload" option is implemented, move the "force-reload"
# option to the "reload" entry above. If not, "force-reload" is
# just the same as "restart" except that it does nothing if the
# daemon isn't already running.
# check wether $DAEMON is running. If so, restart
start-stop-daemon --stop --test --quiet --pidfile \
/var/run/$NAME.pid --exec $DAEMON \
&& $0 restart \
|| exit 0
;;
restart)
echo -n "Restarting $DESC: "
start-stop-daemon --stop --quiet --pidfile \
/var/run/$NAME.pid --exec $DAEMON
[ -n "$DODTIME" ] && sleep $DODTIME
start-stop-daemon --start --quiet --pidfile \
/var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
status)
echo -n "$LABEL is "
if running ; then
echo "running"
else
echo " not running."
exit 1
fi
;;
*)
N=/etc/init.d/$NAME
# echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2
echo "Usage: $N {start|stop|restart|force-reload|status|force-stop}" >&2
exit 1
;;
esac
exit 0

39
debian/postinst vendored
View File

@@ -1,39 +0,0 @@
#!/bin/sh
# postinst script for uhub
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
configure)
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

37
debian/postrm vendored
View File

@@ -1,37 +0,0 @@
#!/bin/sh
# postrm script for uhub
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postrm> `remove'
# * <postrm> `purge'
# * <old-postrm> `upgrade' <new-version>
# * <new-postrm> `failed-upgrade' <old-version>
# * <new-postrm> `abort-install'
# * <new-postrm> `abort-install' <old-version>
# * <new-postrm> `abort-upgrade' <old-version>
# * <disappearer's-postrm> `disappear' <overwriter>
# <overwriter-version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
;;
*)
echo "postrm called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

35
debian/preinst vendored
View File

@@ -1,35 +0,0 @@
#!/bin/sh
# preinst script for uhub
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <new-preinst> `install'
# * <new-preinst> `install' <old-version>
# * <new-preinst> `upgrade' <old-version>
# * <old-preinst> `abort-upgrade' <new-version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
install|upgrade)
;;
abort-upgrade)
;;
*)
echo "preinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

38
debian/prerm vendored
View File

@@ -1,38 +0,0 @@
#!/bin/sh
# prerm script for uhub
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <prerm> `remove'
# * <old-prerm> `upgrade' <new-version>
# * <new-prerm> `failed-upgrade' <old-version>
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
# * <deconfigured's-prerm> `deconfigure' `in-favour'
# <package-being-installed> <version> `removing'
# <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
remove|upgrade|deconfigure)
;;
failed-upgrade)
;;
*)
echo "prerm called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

91
debian/rules vendored
View File

@@ -1,91 +0,0 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
configure: configure-stamp
configure-stamp:
dh_testdir
# Add here commands to configure the package.
touch configure-stamp
build: build-stamp
build-stamp: configure-stamp
dh_testdir
# Add here commands to compile the package.
$(MAKE)
#docbook-to-man debian/uhub.sgml > uhub.1
touch $@
clean:
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
# Add here commands to clean up after the build process.
$(MAKE) clean
dh_clean
install: build
dh_testdir
dh_testroot
dh_prep
dh_installdirs
# Add here commands to install the package into debian/uhub.
$(MAKE) DESTDIR=$(CURDIR)/debian/uhub install
# Build architecture-independent files here.
binary-indep: install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: install
dh_testdir
dh_testroot
dh_installchangelogs ChangeLog
dh_installdocs
dh_installexamples
# dh_install
# dh_installmenu
# dh_installdebconf
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_python
# dh_installinit
# dh_installcron
# dh_installinfo
dh_installman
dh_link
dh_strip
dh_compress
dh_fixperms
# dh_perl
# dh_makeshlibs
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure

10
debian/uhub.default vendored
View File

@@ -1,10 +0,0 @@
# Defaults for uhub initscript
# sourced by /etc/init.d/uhub
# installed at /etc/default/uhub by the maintainer scripts
# Additional options that are passed to the Daemon.
ENABLED=1
LOGFILE="/var/log/uhug.log"
USER=nobody
GROUP=nogroup
DAEMON_OPTS="-f -l ${LOGFILE} -u ${USER} -g {GROUP}"

72
doc/uhub.1 Normal file
View File

@@ -0,0 +1,72 @@
.TH UHUB 1 "March 2009"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
.\" .nh disable hyphenation
.\" .hy enable hyphenation
.\" .ad l left justify
.\" .ad b justify to both left and right margins
.\" .nf disable filling
.\" .fi enable filling
.\" .br insert line break
.\" .sp <n> insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
uhub \- a high performance ADC peer-to-peer hub
.SH SYNOPSIS
.B uhub
.RI [ options ]
.SH 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.
.SH "OPTIONS"
.TP
.BI \^\-v
Verbose mode, add more -v's for higher verbosity.
.TP
.BI \^\-q
Quiet mode, if quiet mode is enabled no output or logs are made.
.TP
.BI \^\-f
Fork uhub to background in order to run it as a daemon.
.TP
.BI \^\-l " logfile"
Log messages to the given logfile (default: stderr)
.TP
.BI \^\-L
Log messages to syslog.
.TP
.BI \^\-c " config"
Specify configuration file (default: /etc/uhub/uhub.conf)
.TP
.BI \^\-C
Check configuration files and return. Will print either \"OK\" or \"ERROR\".
.TP
.BI \^\-s
Show all configuration parameters. In a format that is compatible with
the configuration files.
.TP
.BI \^\-S
Show all non-default configuration parameters.
.TP
.BI \^\-h
Show the help message.
.TP
.BI \^\-u " user"
Drop privileges and run as the given user.
.TP
.BI \^\-g " group"
Drop privileges and run with the given group permissions.
.TP
.BI \^\-V
Show the version number
.SH EXAMPLES
To run uhub as a daemon, and log to a file:
.TP
.B uhub " -f -l /var/log/uhub/uhub.log"
.SH AUTHOR
This program was written by Jan Vidar Krey <janvidar@extatic.org>
.SH "BUG REPORTS"
If you find a bug in uhub please report it to
.B http://bugs.extatic.org/

View File

@@ -23,7 +23,7 @@
#define ACL_ADD_BOOL(S, L) do { ret = check_cmd_bool(S, L, line, line_count); if (ret != 0) return ret; } while(0) #define ACL_ADD_BOOL(S, L) do { ret = check_cmd_bool(S, L, line, line_count); if (ret != 0) return ret; } while(0)
#define ACL_ADD_ADDR(S, L) do { ret = check_cmd_addr(S, L, line, line_count); if (ret != 0) return ret; } while(0) #define ACL_ADD_ADDR(S, L) do { ret = check_cmd_addr(S, L, line, line_count); if (ret != 0) return ret; } while(0)
static const char* get_user_credential_string(enum user_credentials cred) const char* get_user_credential_string(enum user_credentials cred)
{ {
switch (cred) switch (cred)
{ {

View File

@@ -48,6 +48,8 @@ enum user_credentials
cred_link, /**<<< "User is a link (not used currently)" */ cred_link, /**<<< "User is a link (not used currently)" */
}; };
const char* get_user_credential_string(enum user_credentials cred);
struct user_access_info struct user_access_info
{ {
char* username; /* name of user, cid or IP range */ char* username; /* name of user, cid or IP range */

View File

@@ -19,74 +19,96 @@
#include "uhub.h" #include "uhub.h"
static int command_access_denied(struct user* user) typedef int (*command_handler)(struct hub_info* hub, struct user* user, const char* message);
struct commands_handler
{ {
struct adc_message* command; const char* prefix;
char* buffer = adc_msg_escape("Access denied."); size_t length;
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6); enum user_credentials cred;
command_handler handler;
const char* description;
};
static struct commands_handler command_handlers[];
static void send_message(struct hub_info* hub, struct user* user, const char* message)
{
char* buffer = adc_msg_escape(message);
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer); adc_msg_add_argument(command, buffer);
route_to_user(user, command); route_to_user(user, command);
adc_msg_free(command); adc_msg_free(command);
hub_free(buffer); hub_free(buffer);
return 0;
} }
static int command_access_denied(struct hub_info* hub, struct user* user, const char* command)
static int command_stats(struct user* user, const char* message)
{ {
struct adc_message* command;
if (user->credentials < cred_super)
return command_access_denied(user);
char temp[128]; char temp[128];
snprintf(temp, 128, "*** Access denied: \"%s\"", command);
snprintf(temp, 128, "*** Stats: %zu users, peak: %zu. Network (up/down): %d/%d KB/s, peak: %d/%d KB/s", send_message(hub, user, temp);
user->hub->users->count,
user->hub->users->count_peak,
(int) user->hub->stats.net_tx / 1024,
(int) user->hub->stats.net_rx / 1024,
(int) user->hub->stats.net_tx_peak / 1024,
(int) user->hub->stats.net_rx_peak / 1024);
char* buffer = adc_msg_escape(temp);
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_user(user, command);
adc_msg_free(command);
hub_free(buffer);
return 0; return 0;
} }
static int command_not_found(struct hub_info* hub, struct user* user, const char* command)
static int command_help(struct user* user, const char* message)
{ {
struct adc_message* command; char temp[128];
char* buffer = adc_msg_escape("\n" snprintf(temp, 128, "*** Command not found: \"%s\"", command);
"*** Available commands:\n" send_message(hub, user, temp);
"!help - Show this help message\n"
"!stats - Show hub stats (super)\n"
"!version - Show this help message\n"
"!uptime - Display hub uptime\n"
"!kick <user> - Kick user (operator)\n"
);
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_user(user, command);
adc_msg_free(command);
hub_free(buffer);
return 0; return 0;
} }
static int command_uptime(struct user* user, const char* message) static int command_status(struct hub_info* hub, struct user* user, const char* command, const char* message)
{
char temp[1024];
snprintf(temp, 1024, "*** %s: %s", command, message);
send_message(hub, user, temp);
return 0;
}
static int command_stats(struct hub_info* hub, struct user* user, const char* message)
{
char temp[128];
snprintf(temp, 128, "%zu users, peak: %zu. Network (up/down): %d/%d KB/s, peak: %d/%d KB/s",
hub->users->count,
hub->users->count_peak,
(int) hub->stats.net_tx / 1024,
(int) hub->stats.net_rx / 1024,
(int) hub->stats.net_tx_peak / 1024,
(int) hub->stats.net_rx_peak / 1024);
return command_status(hub, user, "stats", message);
}
static int command_help(struct hub_info* hub, struct user* user, const char* message)
{
#define MAX_HELP_MSG 1024
size_t n;
char msg[MAX_HELP_MSG];
msg[0] = 0;
strcat(msg, "Available commands:\n");
for (n = 0; command_handlers[n].prefix; n++)
{
if (command_handlers[n].cred <= user->credentials)
{
strcat(msg, "!");
strcat(msg, command_handlers[n].prefix);
strcat(msg, " - ");
strcat(msg, command_handlers[n].description);
strcat(msg, "\n");
}
}
return command_status(hub, user, "help", msg);
}
static int command_uptime(struct hub_info* hub, struct user* user, const char* message)
{ {
struct adc_message* command;
char tmp[128]; char tmp[128];
size_t d; size_t d;
size_t h; size_t h;
size_t m; size_t m;
size_t D = (size_t) difftime(time(0), user->hub->tm_started); size_t D = (size_t) difftime(time(0), hub->tm_started);
d = D / (24 * 3600); d = D / (24 * 3600);
D = D % (24 * 3600); D = D % (24 * 3600);
@@ -95,8 +117,6 @@ static int command_uptime(struct user* user, const char* message)
m = D / 60; m = D / 60;
tmp[0] = 0; tmp[0] = 0;
strcat(tmp, "*** Uptime: ");
if (d) if (d)
{ {
strcat(tmp, uhub_itoa((int) d)); strcat(tmp, uhub_itoa((int) d));
@@ -111,73 +131,88 @@ static int command_uptime(struct user* user, const char* message)
if (m < 10) strcat(tmp, "0"); if (m < 10) strcat(tmp, "0");
strcat(tmp, uhub_itoa((int) m)); strcat(tmp, uhub_itoa((int) m));
char* buffer = adc_msg_escape(tmp); return command_status(hub, user, "uptime", tmp);
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_user(user, command);
adc_msg_free(command);
hub_free(buffer);
return 0;
} }
static int command_kick(struct user* user, const char* message) static int command_kick(struct hub_info* hub, struct user* user, const char* message)
{ {
struct adc_message* command; if (strlen(message) < 7)
{
if (user->credentials < cred_operator) return command_status(hub, user, "kick", "No nickname given");
return command_access_denied(user);
char* buffer = adc_msg_escape("*** Kick not implemented!");
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_user(user, command);
adc_msg_free(command);
hub_free(buffer);
return 0;
} }
static int command_version(struct user* user, const char* message) const char* nick = &message[7];
struct user* target = uman_get_user_by_nick(hub, nick);
if (!target)
{ {
struct adc_message* command; return command_status(hub, user, "kick", "No such user");
char* buffer = adc_msg_escape("*** Powered by " PRODUCT "/" VERSION);
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_user(user, command);
adc_msg_free(command);
hub_free(buffer);
return 0;
} }
static int command_myip(struct user* user, const char* message) if (target == user)
{
return command_status(hub, user, "kick", "Cannot kick yourself");
}
user_disconnect(target, quit_kicked);
return command_status(hub, user, "kick", nick);
}
static int command_reload(struct hub_info* hub, struct user* user, const char* message)
{
hub->status = hub_status_restart;
return command_status(hub, user, "reload", "Reloading configuration...");
}
static int command_shutdown(struct hub_info* hub, struct user* user, const char* message)
{
hub->status = hub_status_shutdown;
return command_status(hub, user, "shutdown", "Hub shutting down...");
}
static int command_version(struct hub_info* hub, struct user* user, const char* message)
{
return command_status(hub, user, "version", "Powered by " PRODUCT "/" VERSION);
}
static int command_myip(struct hub_info* hub, struct user* user, const char* message)
{ {
struct adc_message* command;
char tmp[128]; char tmp[128];
char* buffer; snprintf(tmp, 128, "Your IP is \"%s\"", ip_convert_to_string(&user->ipaddr));
return command_status(hub, user, "myip", tmp);
tmp[0] = 0;
strcat(tmp, "*** Your IP: ");
strcat(tmp, ip_convert_to_string(&user->ipaddr));
buffer = adc_msg_escape(tmp);
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_user(user, command);
adc_msg_free(command);
hub_free(buffer);
return 0;
} }
int command_dipatcher(struct hub_info* hub, struct user* user, const char* message)
int command_dipatcher(struct user* user, const char* message)
{ {
if (!strncmp(message, "!stats", 6)) command_stats(user, message); size_t n = 0;
else if (!strncmp(message, "!help", 5)) command_help(user, message); for (n = 0; command_handlers[n].prefix; n++)
else if (!strncmp(message, "!kick", 5)) command_kick(user, message); {
else if (!strncmp(message, "!version", 8)) command_version(user, message); if (!strncmp(message, command_handlers[n].prefix, command_handlers[n].length))
else if (!strncmp(message, "!uptime", 7)) command_uptime(user, message); {
else if (!strncmp(message, "+myip", 5)) command_myip(user, message); if (command_handlers[n].cred <= user->credentials)
{
return command_handlers[n].handler(hub, user, message);
}
else else
return 1; {
return 0; return command_access_denied(hub, user, command_handlers[n].prefix);
}
}
} }
command_not_found(hub, user, message);
return 1;
}
static struct commands_handler command_handlers[] = {
{ "help", 4, cred_guest, command_help, "Show this help message." },
{ "stats", 5, cred_super, command_stats, "Show hub statistics." },
{ "version", 7, cred_guest, command_version, "Show hub version info." },
{ "uptime", 6, cred_guest, command_uptime, "Display hub uptime info." },
{ "kick", 4, cred_operator, command_kick, "Kick a user" },
{ "reload", 6, cred_admin, command_reload, "Reload configuration files." },
{ "shutdown", 8, cred_admin, command_shutdown, "Shutdown hub." },
{ "myip", 4, cred_guest, command_myip, "Show your own IP." },
{ 0, 0, cred_none, command_help, "" }
};

View File

@@ -32,4 +32,4 @@ struct command_info
plugin_event_chat_message function; plugin_event_chat_message function;
}; };
int command_dipatcher(struct user* user, const char* message); int command_dipatcher(struct hub_info* hub, struct user* user, const char* message);

View File

@@ -464,6 +464,11 @@ static int config_parse_line(char* line, int line_count, void* ptr_data)
hub_log(log_trace, "config_parse_line(): '%s'", line); hub_log(log_trace, "config_parse_line(): '%s'", line);
#endif #endif
if (!is_valid_utf8(line))
{
hub_log(log_warning, "Invalid utf-8 characters on line %d", line_count);
}
if ((pos = strchr(line, '=')) != NULL) if ((pos = strchr(line, '=')) != NULL)
{ {
pos[0] = 0; pos[0] = 0;

331
src/hub.c
View File

@@ -19,7 +19,7 @@
#include "uhub.h" #include "uhub.h"
int hub_handle_message(struct user* u, const char* line, size_t length) int hub_handle_message(struct hub_info* hub, struct user* u, const char* line, size_t length)
{ {
int ret = 0; int ret = 0;
struct adc_message* cmd = 0; struct adc_message* cmd = 0;
@@ -36,13 +36,9 @@ int hub_handle_message(struct user* u, const char* line, size_t length)
{ {
switch (cmd->cmd) switch (cmd->cmd)
{ {
case ADC_CMD_HSUP: ret = hub_handle_support(u, cmd); break; case ADC_CMD_HSUP: ret = hub_handle_support(hub, u, cmd); break;
case ADC_CMD_HPAS: ret = hub_handle_password(u, cmd); break; case ADC_CMD_HPAS: ret = hub_handle_password(hub, u, cmd); break;
case ADC_CMD_BINF: ret = hub_handle_info(u, cmd); break; case ADC_CMD_BINF: ret = hub_handle_info(hub, u, cmd); break;
#ifdef ADC_UDP_OPERATION
case ADC_CMD_HCHK: ret = hub_handle_autocheck(u, cmd); break;
#endif
case ADC_CMD_DINF: case ADC_CMD_DINF:
case ADC_CMD_EINF: case ADC_CMD_EINF:
case ADC_CMD_FINF: case ADC_CMD_FINF:
@@ -54,7 +50,7 @@ int hub_handle_message(struct user* u, const char* line, size_t length)
case ADC_CMD_DMSG: case ADC_CMD_DMSG:
case ADC_CMD_BMSG: case ADC_CMD_BMSG:
case ADC_CMD_FMSG: case ADC_CMD_FMSG:
ret = hub_handle_chat_message(u, cmd); ret = hub_handle_chat_message(hub, u, cmd);
break; break;
case ADC_CMD_BSCH: case ADC_CMD_BSCH:
@@ -65,7 +61,7 @@ int hub_handle_message(struct user* u, const char* line, size_t length)
case ADC_CMD_DRCM: case ADC_CMD_DRCM:
case ADC_CMD_DCTM: case ADC_CMD_DCTM:
cmd->priority = -1; cmd->priority = -1;
if (u->hub->config->chat_only && u->credentials < cred_operator) if (hub->config->chat_only && u->credentials < cred_operator)
{ {
/* These below aren't allowed in chat only hubs */ /* These below aren't allowed in chat only hubs */
break; break;
@@ -96,7 +92,7 @@ int hub_handle_message(struct user* u, const char* line, size_t length)
} }
int hub_handle_support(struct user* u, struct adc_message* cmd) int hub_handle_support(struct hub_info* hub, struct user* u, struct adc_message* cmd)
{ {
int ret = 0; int ret = 0;
int index = 0; int index = 0;
@@ -104,9 +100,9 @@ int hub_handle_support(struct user* u, struct adc_message* cmd)
char* arg = adc_msg_get_argument(cmd, index); char* arg = adc_msg_get_argument(cmd, index);
struct timeval timeout = { TIMEOUT_HANDSHAKE, 0 }; struct timeval timeout = { TIMEOUT_HANDSHAKE, 0 };
if (u->hub->status == hub_status_disabled && u->state == state_protocol) if (hub->status == hub_status_disabled && u->state == state_protocol)
{ {
on_login_failure(u, status_msg_hub_disabled); on_login_failure(hub, u, status_msg_hub_disabled);
return -1; return -1;
} }
@@ -145,7 +141,7 @@ int hub_handle_support(struct user* u, struct adc_message* cmd)
if (ok) if (ok)
{ {
hub_send_handshake(u); hub_send_handshake(hub, u);
if (u->ev_read) if (u->ev_read)
event_add(u->ev_read, &timeout); event_add(u->ev_read, &timeout);
} }
@@ -161,7 +157,7 @@ int hub_handle_support(struct user* u, struct adc_message* cmd)
} }
int hub_handle_password(struct user* u, struct adc_message* cmd) int hub_handle_password(struct hub_info* hub, struct user* u, struct adc_message* cmd)
{ {
char* password = adc_msg_get_argument(cmd, 0); char* password = adc_msg_get_argument(cmd, 0);
int ret = 0; int ret = 0;
@@ -170,11 +166,11 @@ int hub_handle_password(struct user* u, struct adc_message* cmd)
{ {
if (password_verify(u, password)) if (password_verify(u, password))
{ {
on_login_success(u); on_login_success(hub, u);
} }
else else
{ {
on_login_failure(u, status_msg_auth_invalid_password); on_login_failure(hub, u, status_msg_auth_invalid_password);
ret = -1; ret = -1;
} }
} }
@@ -184,7 +180,7 @@ int hub_handle_password(struct user* u, struct adc_message* cmd)
} }
int hub_handle_chat_message(struct user* u, struct adc_message* cmd) int hub_handle_chat_message(struct hub_info* hub, struct user* u, struct adc_message* cmd)
{ {
char* message = adc_msg_get_argument(cmd, 0); char* message = adc_msg_get_argument(cmd, 0);
int ret = 0; int ret = 0;
@@ -193,7 +189,7 @@ int hub_handle_chat_message(struct user* u, struct adc_message* cmd)
/* TODO: Check for hub-commands here. Set relay to 0 and the message will not be sent to other users. */ /* TODO: Check for hub-commands here. Set relay to 0 and the message will not be sent to other users. */
if (message[0] == '!' || message[0] == '+') if (message[0] == '!' || message[0] == '+')
{ {
relay = command_dipatcher(u, message); relay = command_dipatcher(hub, u, message);
} }
if (relay && user_is_logged_in(u)) if (relay && user_is_logged_in(u))
@@ -206,67 +202,22 @@ int hub_handle_chat_message(struct user* u, struct adc_message* cmd)
return ret; return ret;
} }
int on_kick(struct user* u, struct adc_message* cmd) void hub_send_support(struct hub_info* hub, struct user* u)
{
hub_log(log_error, "on_kick() not implemented");
return -1;
}
#ifdef ADC_UDP_OPERATION
int hub_handle_autocheck(struct user* u, struct adc_message* cmd)
{
char* port_str = adc_msg_get_argument(cmd, 0);
char* token = adc_msg_get_argument(cmd, 1);
int port = 0;
if (!port_str || !token || strlen(token) != 4)
{
hub_free(port_str);
hub_free(token);
return -1;
}
port = uhub_atoi(port_str);
if (port == 0 || port > 65535)
{
hub_free(port_str);
hub_free(token);
return -1;
}
hub_send_autocheck(u, port, token);
hub_free(port_str);
hub_free(token);
return 0;
}
#endif
void hub_send_autocheck(struct user* u, uint16_t port, const char* token)
{
}
void hub_send_support(struct user* u)
{ {
if (user_is_connecting(u) || user_is_logged_in(u)) if (user_is_connecting(u) || user_is_logged_in(u))
{ {
route_to_user(u, u->hub->command_support); route_to_user(u, hub->command_support);
} }
} }
void hub_send_sid(struct user* u) void hub_send_sid(struct hub_info* hub, struct user* u)
{ {
struct adc_message* command; struct adc_message* command;
if (user_is_connecting(u)) if (user_is_connecting(u))
{ {
command = adc_msg_construct(ADC_CMD_ISID, 10); command = adc_msg_construct(ADC_CMD_ISID, 10);
u->id.sid = user_manager_get_free_sid(u->hub); u->id.sid = uman_get_free_sid(hub);
adc_msg_add_argument(command, (const char*) sid_to_string(u->id.sid)); adc_msg_add_argument(command, (const char*) sid_to_string(u->id.sid));
route_to_user(u, command); route_to_user(u, command);
adc_msg_free(command); adc_msg_free(command);
@@ -274,7 +225,7 @@ void hub_send_sid(struct user* u)
} }
void hub_send_ping(struct user* user) void hub_send_ping(struct hub_info* hub, struct user* user)
{ {
/* This will just send a newline, despite appearing to do more below. */ /* This will just send a newline, despite appearing to do more below. */
struct adc_message* ping = adc_msg_construct(0, 0); struct adc_message* ping = adc_msg_construct(0, 0);
@@ -287,9 +238,9 @@ void hub_send_ping(struct user* user)
} }
void hub_send_hubinfo(struct user* u) void hub_send_hubinfo(struct hub_info* hub, struct user* u)
{ {
struct adc_message* info = adc_msg_copy(u->hub->command_info); struct adc_message* info = adc_msg_copy(hub->command_info);
int value = 0; int value = 0;
if (user_flag_get(u, feature_ping)) if (user_flag_get(u, feature_ping))
@@ -301,43 +252,43 @@ void hub_send_hubinfo(struct user* u)
NE - Hub Network NE - Hub Network
OW - Hub Owner name OW - Hub Owner name
*/ */
adc_msg_add_named_argument(info, "UC", uhub_itoa(hub_get_user_count(u->hub))); adc_msg_add_named_argument(info, "UC", uhub_itoa(hub_get_user_count(hub)));
adc_msg_add_named_argument(info, "MC", uhub_itoa(hub_get_max_user_count(u->hub))); adc_msg_add_named_argument(info, "MC", uhub_itoa(hub_get_max_user_count(hub)));
adc_msg_add_named_argument(info, "SS", uhub_ulltoa(hub_get_shared_size(u->hub))); adc_msg_add_named_argument(info, "SS", uhub_ulltoa(hub_get_shared_size(hub)));
adc_msg_add_named_argument(info, "SF", uhub_itoa(hub_get_shared_files(u->hub))); adc_msg_add_named_argument(info, "SF", uhub_itoa(hub_get_shared_files(hub)));
/* Maximum/minimum share size */ /* Maximum/minimum share size */
value = hub_get_max_share(u->hub); value = hub_get_max_share(hub);
if (value) adc_msg_add_named_argument(info, "XS", uhub_itoa(value)); if (value) adc_msg_add_named_argument(info, "XS", uhub_itoa(value));
value = hub_get_min_share(u->hub); value = hub_get_min_share(hub);
if (value) adc_msg_add_named_argument(info, "MS", uhub_itoa(value)); if (value) adc_msg_add_named_argument(info, "MS", uhub_itoa(value));
/* Maximum/minimum upload slots allowed per user */ /* Maximum/minimum upload slots allowed per user */
value = hub_get_max_slots(u->hub); value = hub_get_max_slots(hub);
if (value) adc_msg_add_named_argument(info, "XL", uhub_itoa(value)); if (value) adc_msg_add_named_argument(info, "XL", uhub_itoa(value));
value = hub_get_min_slots(u->hub); value = hub_get_min_slots(hub);
if (value) adc_msg_add_named_argument(info, "ML", uhub_itoa(value)); if (value) adc_msg_add_named_argument(info, "ML", uhub_itoa(value));
/* guest users must be on min/max hubs */ /* guest users must be on min/max hubs */
value = hub_get_max_hubs_user(u->hub); value = hub_get_max_hubs_user(hub);
if (value) adc_msg_add_named_argument(info, "XU", uhub_itoa(value)); if (value) adc_msg_add_named_argument(info, "XU", uhub_itoa(value));
value = hub_get_min_hubs_user(u->hub); value = hub_get_min_hubs_user(hub);
if (value) adc_msg_add_named_argument(info, "MU", uhub_itoa(value)); if (value) adc_msg_add_named_argument(info, "MU", uhub_itoa(value));
/* registered users must be on min/max hubs */ /* registered users must be on min/max hubs */
value = hub_get_max_hubs_reg(u->hub); value = hub_get_max_hubs_reg(hub);
if (value) adc_msg_add_named_argument(info, "XR", uhub_itoa(value)); if (value) adc_msg_add_named_argument(info, "XR", uhub_itoa(value));
value = hub_get_min_hubs_reg(u->hub); value = hub_get_min_hubs_reg(hub);
if (value) adc_msg_add_named_argument(info, "MR", uhub_itoa(value)); if (value) adc_msg_add_named_argument(info, "MR", uhub_itoa(value));
/* operators must be on min/max hubs */ /* operators must be on min/max hubs */
value = hub_get_max_hubs_op(u->hub); value = hub_get_max_hubs_op(hub);
if (value) adc_msg_add_named_argument(info, "XO", uhub_itoa(value)); if (value) adc_msg_add_named_argument(info, "XO", uhub_itoa(value));
value = hub_get_min_hubs_op(u->hub); value = hub_get_min_hubs_op(hub);
if (value) adc_msg_add_named_argument(info, "MO", uhub_itoa(value)); if (value) adc_msg_add_named_argument(info, "MO", uhub_itoa(value));
/* uptime in seconds */ /* uptime in seconds */
adc_msg_add_named_argument(info, "UP", uhub_itoa((int) difftime(time(0), u->hub->tm_started))); adc_msg_add_named_argument(info, "UP", uhub_itoa((int) difftime(time(0), hub->tm_started)));
} }
if (user_is_connecting(u) || user_is_logged_in(u)) if (user_is_connecting(u) || user_is_logged_in(u))
@@ -347,20 +298,17 @@ void hub_send_hubinfo(struct user* u)
adc_msg_free(info); adc_msg_free(info);
/* Only send banner when connecting */ /* Only send banner when connecting */
if (u->hub->config->show_banner && user_is_connecting(u)) if (hub->config->show_banner && user_is_connecting(u))
{ {
route_to_user(u, u->hub->command_banner); route_to_user(u, hub->command_banner);
}
} }
void hub_send_handshake(struct hub_info* hub, struct user* u)
}
void hub_send_handshake(struct user* u)
{ {
hub_send_support(u); hub_send_support(hub, u);
hub_send_sid(u); hub_send_sid(hub, u);
hub_send_hubinfo(u); hub_send_hubinfo(hub, u);
if (!user_is_disconnecting(u)) if (!user_is_disconnecting(u))
{ {
@@ -368,17 +316,15 @@ void hub_send_handshake(struct user* u)
} }
} }
void hub_send_motd(struct hub_info* hub, struct user* u)
void hub_send_motd(struct user* u)
{ {
if (u->hub->command_motd) if (hub->command_motd)
{ {
route_to_user(u, u->hub->command_motd); route_to_user(u, hub->command_motd);
} }
} }
void hub_send_password_challenge(struct hub_info* hub, struct user* u)
void hub_send_password_challenge(struct user* u)
{ {
struct adc_message* igpa; struct adc_message* igpa;
igpa = adc_msg_construct(ADC_CMD_IGPA, 38); igpa = adc_msg_construct(ADC_CMD_IGPA, 38);
@@ -390,8 +336,8 @@ void hub_send_password_challenge(struct user* u)
static void hub_event_dispatcher(void* callback_data, struct event_data* message) static void hub_event_dispatcher(void* callback_data, struct event_data* message)
{ {
/*
struct hub_info* hub = (struct hub_info*) callback_data; struct hub_info* hub = (struct hub_info*) callback_data;
/*
hub_log(log_trace, "hub_event_dispatcher: %x (ptr=%p)", message->id, message->ptr); hub_log(log_trace, "hub_event_dispatcher: %x (ptr=%p)", message->id, message->ptr);
*/ */
@@ -404,20 +350,20 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message
if (message->flags) if (message->flags)
{ {
hub_send_password_challenge((struct user*) message->ptr); hub_send_password_challenge(hub, (struct user*) message->ptr);
} }
else else
{ {
on_login_success((struct user*) message->ptr); on_login_success(hub, (struct user*) message->ptr);
} }
break; break;
} }
case UHUB_EVENT_USER_QUIT: case UHUB_EVENT_USER_QUIT:
{ {
user_manager_remove((struct user*) message->ptr); uman_remove(hub, (struct user*) message->ptr);
send_quit_message((struct user*) message->ptr); uman_send_quit_message((struct user*) message->ptr);
on_logout_user((struct user*) message->ptr); on_logout_user(hub, (struct user*) message->ptr);
user_schedule_destroy((struct user*) message->ptr); user_schedule_destroy((struct user*) message->ptr);
break; break;
} }
@@ -439,12 +385,9 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message
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;
int server_tcp, ret, ipv6_supported, af;
#ifdef ADC_UDP_OPERATION
int server_udp;
#endif
struct sockaddr_storage addr; struct sockaddr_storage addr;
socklen_t sockaddr_size; socklen_t sockaddr_size;
int server_tcp, ret, ipv6_supported, af;
char address_buf[INET6_ADDRSTRLEN+1]; char address_buf[INET6_ADDRSTRLEN+1];
hub = hub_malloc_zero(sizeof(struct hub_info)); hub = hub_malloc_zero(sizeof(struct hub_info));
@@ -479,7 +422,11 @@ struct hub_info* hub_start_service(struct hub_config* config)
net_address_to_string(AF_INET6, &((struct sockaddr_in6*) &addr)->sin6_addr, address_buf, INET6_ADDRSTRLEN); net_address_to_string(AF_INET6, &((struct sockaddr_in6*) &addr)->sin6_addr, address_buf, INET6_ADDRSTRLEN);
} }
#ifdef LIBEVENT_1_4
hub->evbase = event_base_new(); hub->evbase = event_base_new();
#else
hub->evbase = event_init();
#endif
if (!hub->evbase) if (!hub->evbase)
{ {
hub_log(log_error, "Unable to initialize libevent."); hub_log(log_error, "Unable to initialize libevent.");
@@ -487,7 +434,8 @@ struct hub_info* hub_start_service(struct hub_config* config)
return 0; return 0;
} }
hub_log(log_info, "Starting server, listening on %s:%d...", address_buf, config->server_port); hub_log(log_info, "Starting " PRODUCT "/" VERSION ", listening on %s:%d...", address_buf, config->server_port);
hub_log(log_debug, "Using libevent %s, backend: %s", event_get_version(), event_get_method());
server_tcp = net_socket_create(af, SOCK_STREAM, IPPROTO_TCP); server_tcp = net_socket_create(af, SOCK_STREAM, IPPROTO_TCP);
if (server_tcp == -1) if (server_tcp == -1)
@@ -497,66 +445,24 @@ struct hub_info* hub_start_service(struct hub_config* config)
return 0; return 0;
} }
#ifdef ADC_UDP_OPERATION
server_udp = net_socket_create(af, SOCK_DGRAM, IPPROTO_UDP);
if (server_udp == -1)
{
event_base_free(hub->evbase);
hub_free(hub);
return 0;
}
#endif
ret = net_set_reuseaddress(server_tcp, 1); ret = net_set_reuseaddress(server_tcp, 1);
if (ret == -1) if (ret == -1)
{ {
event_base_free(hub->evbase); event_base_free(hub->evbase);
hub_free(hub); hub_free(hub);
net_close(server_tcp); net_close(server_tcp);
#ifdef ADC_UDP_OPERATION
net_close(server_udp);
#endif
return 0; return 0;
} }
#ifdef ADC_UDP_OPERATION
ret = net_set_reuseaddress(server_udp, 1);
if (ret == -1)
{
event_base_free(hub->evbase);
hub_free(hub);
net_close(server_tcp);
net_close(server_udp);
return 0;
}
#endif
ret = net_set_nonblocking(server_tcp, 1); ret = net_set_nonblocking(server_tcp, 1);
if (ret == -1) if (ret == -1)
{ {
event_base_free(hub->evbase); event_base_free(hub->evbase);
hub_free(hub); hub_free(hub);
net_close(server_tcp); net_close(server_tcp);
#ifdef ADC_UDP_OPERATION
net_close(server_udp);
#endif
return 0; return 0;
} }
#ifdef ADC_UDP_OPERATION
ret = net_set_nonblocking(server_udp, 1);
if (ret == -1)
{
event_base_free(hub->evbase);
hub_free(hub);
net_close(server_tcp);
net_close(server_udp);
return 0;
}
#endif
ret = net_bind(server_tcp, (struct sockaddr*) &addr, sockaddr_size); ret = net_bind(server_tcp, (struct sockaddr*) &addr, sockaddr_size);
if (ret == -1) if (ret == -1)
{ {
@@ -564,25 +470,9 @@ struct hub_info* hub_start_service(struct hub_config* config)
event_base_free(hub->evbase); event_base_free(hub->evbase);
hub_free(hub); hub_free(hub);
net_close(server_tcp); net_close(server_tcp);
#ifdef ADC_UDP_OPERATION
net_close(server_udp);
#endif
return 0; return 0;
} }
#ifdef ADC_UDP_OPERATION
ret = net_bind(server_udp, (struct sockaddr*) &addr, sockaddr_size);
if (ret == -1)
{
hub_log(log_fatal, "hub_start_service(): Unable to bind to UDP local address. errno=%d, str=%s", net_error(), net_error_string(net_error()));
event_base_free(hub->evbase);
hub_free(hub);
net_close(server_tcp);
net_close(server_udp);
return 0;
}
#endif
ret = net_listen(server_tcp, SERVER_BACKLOG); ret = net_listen(server_tcp, SERVER_BACKLOG);
if (ret == -1) if (ret == -1)
{ {
@@ -590,26 +480,17 @@ struct hub_info* hub_start_service(struct hub_config* config)
event_base_free(hub->evbase); event_base_free(hub->evbase);
hub_free(hub); hub_free(hub);
net_close(server_tcp); net_close(server_tcp);
#ifdef ADC_UDP_OPERATION
net_close(server_udp);
#endif
return 0; return 0;
} }
hub->fd_tcp = server_tcp; hub->fd_tcp = server_tcp;
#ifdef ADC_UDP_OPERATION
hub->fd_udp = server_udp;
#endif
hub->config = config; hub->config = config;
hub->users = NULL; hub->users = NULL;
if (user_manager_init(hub) == -1) if (uman_init(hub) == -1)
{ {
hub_free(hub); hub_free(hub);
net_close(server_tcp); net_close(server_tcp);
#ifdef ADC_UDP_OPERATION
net_close(server_udp);
#endif
return 0; return 0;
} }
@@ -617,36 +498,17 @@ struct hub_info* hub_start_service(struct hub_config* config)
event_base_set(hub->evbase, &hub->ev_accept); event_base_set(hub->evbase, &hub->ev_accept);
if (event_add(&hub->ev_accept, NULL) == -1) if (event_add(&hub->ev_accept, NULL) == -1)
{ {
user_manager_shutdown(hub); uman_shutdown(hub);
hub_free(hub); hub_free(hub);
net_close(server_tcp); net_close(server_tcp);
#ifdef ADC_UDP_OPERATION
net_close(server_udp);
#endif
return 0; return 0;
} }
#ifdef ADC_UDP_OPERATION
event_set(&hub->ev_datagram, hub->fd_udp, EV_READ | EV_PERSIST, net_on_packet, hub);
event_base_set(hub->evbase, &hub->ev_datagram);
if (event_add(&hub->ev_datagram, NULL) == -1)
{
user_manager_shutdown(hub);
hub_free(hub);
net_close(server_tcp);
net_close(server_udp);
return 0;
}
#endif
if (event_queue_initialize(&hub->queue, hub_event_dispatcher, (void*) hub) == -1) if (event_queue_initialize(&hub->queue, hub_event_dispatcher, (void*) hub) == -1)
{ {
user_manager_shutdown(hub); uman_shutdown(hub);
hub_free(hub); hub_free(hub);
net_close(server_tcp); net_close(server_tcp);
#ifdef ADC_UDP_OPERATION
net_close(server_udp);
#endif
return 0; return 0;
} }
@@ -662,12 +524,8 @@ void hub_shutdown_service(struct hub_info* hub)
event_queue_shutdown(hub->queue); event_queue_shutdown(hub->queue);
event_del(&hub->ev_accept); event_del(&hub->ev_accept);
#ifdef ADC_UDP_OPERATION
event_del(&hub->ev_datagram);
net_close(hub->fd_udp);
#endif
net_close(hub->fd_tcp); net_close(hub->fd_tcp);
user_manager_shutdown(hub); uman_shutdown(hub);
hub->status = hub_status_stopped; hub->status = hub_status_stopped;
event_base_free(hub->evbase); event_base_free(hub->evbase);
hub_free(hub); hub_free(hub);
@@ -753,7 +611,7 @@ void hub_free_variables(struct hub_info* hub)
*/ */
static inline int is_nick_in_use(struct hub_info* hub, const char* nick) static inline int is_nick_in_use(struct hub_info* hub, const char* nick)
{ {
struct user* lookup = get_user_by_nick(hub, nick); struct user* lookup = uman_get_user_by_nick(hub, nick);
if (lookup) if (lookup)
{ {
return 1; return 1;
@@ -767,7 +625,7 @@ static inline int is_nick_in_use(struct hub_info* hub, const char* nick)
*/ */
static inline int is_cid_in_use(struct hub_info* hub, const char* cid) static inline int is_cid_in_use(struct hub_info* hub, const char* cid)
{ {
struct user* lookup = get_user_by_cid(hub, cid); struct user* lookup = uman_get_user_by_cid(hub, cid);
if (lookup) if (lookup)
{ {
return 1; return 1;
@@ -792,9 +650,9 @@ static void set_status_code(enum msg_status_level level, int code, char buffer[4
* @param msg See enum status_message * @param msg See enum status_message
* @param level See enum status_level * @param level See enum status_level
*/ */
void hub_send_status(struct user* user, enum status_message msg, enum msg_status_level level) void hub_send_status(struct hub_info* hub, struct user* user, enum status_message msg, enum msg_status_level level)
{ {
struct hub_config* cfg = user->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; if (!cmd) return;
char code[4]; char code[4];
@@ -894,6 +752,46 @@ const char* hub_get_status_message(struct hub_info* hub, enum status_message msg
return "Unknown"; return "Unknown";
} }
const char* hub_get_status_message_log(struct hub_info* hub, enum status_message msg)
{
#define STATUS(MSG) case status_ ## MSG : return #MSG; break
switch (msg)
{
STATUS(msg_hub_full);
STATUS(msg_hub_disabled);
STATUS(msg_hub_registered_users_only);
STATUS(msg_inf_error_nick_missing);
STATUS(msg_inf_error_nick_multiple);
STATUS(msg_inf_error_nick_invalid);
STATUS(msg_inf_error_nick_long);
STATUS(msg_inf_error_nick_short);
STATUS(msg_inf_error_nick_spaces);
STATUS(msg_inf_error_nick_bad_chars);
STATUS(msg_inf_error_nick_not_utf8);
STATUS(msg_inf_error_nick_taken);
STATUS(msg_inf_error_nick_restricted);
STATUS(msg_inf_error_cid_invalid);
STATUS(msg_inf_error_cid_missing);
STATUS(msg_inf_error_cid_taken);
STATUS(msg_inf_error_pid_missing);
STATUS(msg_inf_error_pid_invalid);
STATUS(msg_ban_permanently);
STATUS(msg_ban_temporarily);
STATUS(msg_auth_invalid_password);
STATUS(msg_auth_user_not_found);
STATUS(msg_error_no_memory);
STATUS(msg_user_share_size_low);
STATUS(msg_user_share_size_high);
STATUS(msg_user_slots_low);
STATUS(msg_user_slots_high);
STATUS(msg_user_hub_limit_low);
STATUS(msg_user_hub_limit_high);
}
#undef STATUS
return "unknown";
}
size_t hub_get_user_count(struct hub_info* hub) size_t hub_get_user_count(struct hub_info* hub)
{ {
return hub->users->count; return hub->users->count;
@@ -972,17 +870,20 @@ size_t hub_get_min_hubs_op(struct hub_info* hub)
void hub_event_loop(struct hub_info* hub) void hub_event_loop(struct hub_info* hub)
{ {
#if 0
event_dispatch();
#endif
int ret; int ret;
do do
{ {
ret = event_base_loop(hub->evbase, EVLOOP_ONCE); ret = event_base_loop(hub->evbase, EVLOOP_ONCE);
if (ret != 0) if (ret != 0)
{
hub_log(log_debug, "event_base_loop returned: %d", (int) ret);
}
if (ret < 0)
break; break;
event_queue_process(hub->queue); event_queue_process(hub->queue);
} }
while (hub->status == hub_status_running); while (hub->status == hub_status_running || hub->status == hub_status_disabled);
} }

View File

@@ -82,14 +82,8 @@ struct hub_stats
struct hub_info struct hub_info
{ {
int fd_tcp; int fd_tcp;
#ifdef ADC_UDP_OPERATION
int fd_udp;
#endif
struct event ev_accept; struct event ev_accept;
struct event ev_timer; struct event ev_timer;
#ifdef ADC_UDP_OPERATION
struct event ev_datagram;
#endif
struct hub_stats stats; struct hub_stats stats;
struct event_queue* queue; struct event_queue* queue;
struct event_base* evbase; struct event_base* evbase;
@@ -116,106 +110,94 @@ struct hub_info
* *
* @return 0 on success, -1 on error * @return 0 on success, -1 on error
*/ */
extern int hub_handle_message(struct user* u, const char* message, size_t length); extern int hub_handle_message(struct hub_info* hub, struct user* u, const char* message, size_t length);
/** /**
* Handle protocol support/subscription messages received clients. * Handle protocol support/subscription messages received clients.
* *
* @return 0 on success, -1 on error * @return 0 on success, -1 on error
*/ */
extern int hub_handle_support(struct user* u, struct adc_message* cmd); extern int hub_handle_support(struct hub_info* hub, struct user* u, struct adc_message* cmd);
/** /**
* Handle password messages received from clients. * Handle password messages received from clients.
* *
* @return 0 on success, -1 on error * @return 0 on success, -1 on error
*/ */
extern int hub_handle_password(struct user* u, struct adc_message* cmd); extern int hub_handle_password(struct hub_info* hub, struct user* u, struct adc_message* cmd);
/** /**
* Handle chat messages received from clients. * Handle chat messages received from clients.
* @return 0 on success, -1 on error. * @return 0 on success, -1 on error.
*/ */
extern int hub_handle_chat_message(struct user* u, struct adc_message* cmd); extern int hub_handle_chat_message(struct hub_info* hub, struct user* u, struct adc_message* cmd);
/** /**
* Used internally by hub_handle_info * Used internally by hub_handle_info
* @return 1 if nickname is OK, or 0 if nickname is not accepted. * @return 1 if nickname is OK, or 0 if nickname is not accepted.
*/ */
extern int hub_handle_info_check_nick(struct user* u, struct adc_message* cmd); extern int hub_handle_info_check_nick(struct hub_info* hub, struct user* u, struct adc_message* cmd);
/** /**
* Used internally by hub_handle_info * Used internally by hub_handle_info
* @return 1 if CID/PID is OK, or 0 if not valid. * @return 1 if CID/PID is OK, or 0 if not valid.
*/ */
extern int hub_handle_info_check_cid(struct user* u, struct adc_message* cmd); extern int hub_handle_info_check_cid(struct hub_info* hub, struct user* u, struct adc_message* cmd);
/**
* Can only be used by administrators or operators.
*
* @return 0 on success, -1 on error
*/
extern int hub_handle_kick(struct user* u, struct adc_message* cmd);
#ifdef ADC_UDP_OPERATION
/**
* Handle incoming autocheck message.
*/
extern int hub_handle_autocheck(struct user* u, struct adc_message* cmd);
#endif
/** /**
* Send the support line for the hub to a particular user. * Send the support line for the hub to a particular user.
* Only used during the initial handshake. * Only used during the initial handshake.
*/ */
extern void hub_send_support(struct user* u); extern void hub_send_support(struct hub_info* hub, struct user* u);
/** /**
* Send a message assigning a SID for a user. * Send a message assigning a SID for a user.
* This is only sent after hub_send_support() during initial handshake. * This is only sent after hub_send_support() during initial handshake.
*/ */
extern void hub_send_sid(struct user* u); extern void hub_send_sid(struct hub_info* hub, struct user* u);
/** /**
* Send a 'ping' message to user. * Send a 'ping' message to user.
*/ */
extern void hub_send_ping(struct user* user); extern void hub_send_ping(struct hub_info* hub, struct user* user);
/** /**
* Send a message containing hub information to a particular user. * Send a message containing hub information to a particular user.
* This is sent during user connection, but can safely be sent at any * This is sent during user connection, but can safely be sent at any
* point later. * point later.
*/ */
extern void hub_send_hubinfo(struct user* u); extern void hub_send_hubinfo(struct hub_info* hub, struct user* u);
/** /**
* Send handshake. This basically calls * Send handshake. This basically calls
* hub_send_support() and hub_send_sid() * hub_send_support() and hub_send_sid()
*/ */
extern void hub_send_handshake(struct user* u); extern void hub_send_handshake(struct hub_info* hub, struct 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.
*/ */
extern void hub_send_motd(struct user* u); extern void hub_send_motd(struct hub_info* hub, struct user* u);
/** /**
* Send a password challenge to a user. * Send a password challenge to a user.
* This is only used if the user tries to access the hub using a * This is only used if the user tries to access the hub using a
* password protected nick name. * password protected nick name.
*/ */
extern void hub_send_password_challenge(struct user* u); extern void hub_send_password_challenge(struct hub_info* hub, struct user* u);
/** /**
* Send an autocheck message to a user. * Sends a status_message to a user.
* This is basically a UDP message. The user's client can then determine
* if UDP communication works by either hole punching or configuring UPnP.
*/ */
extern void hub_send_autocheck(struct user* u, uint16_t port, const char* token); extern void hub_send_status(struct hub_info*, struct user* user, enum status_message msg, enum msg_status_level level);
/** /**
* This starts the hub. * Allocates memory, initializes the hub based on the configuration,
* and returns a hub handle.
* This hub handle must be passed to hub_shutdown_service() in order to cleanup before exiting.
*
* @return a pointer to the hub info.
*/ */
extern struct hub_info* hub_start_service(struct hub_config* config); extern struct hub_info* hub_start_service(struct hub_config* config);
@@ -238,11 +220,7 @@ extern void hub_free_variables(struct hub_info* hub);
* Returns a string for the given status_message (See enum status_message). * Returns a string for the given status_message (See enum status_message).
*/ */
extern const char* hub_get_status_message(struct hub_info* hub, enum status_message msg); extern const char* hub_get_status_message(struct hub_info* hub, enum status_message msg);
extern const char* hub_get_status_message_log(struct hub_info* hub, enum status_message msg);
/**
* Sends a status_message to a user.
*/
extern void hub_send_status(struct user* user, enum status_message msg, enum msg_status_level level);
/** /**
* Returns the number of logged in users on the hub. * Returns the number of logged in users on the hub.

View File

@@ -19,24 +19,48 @@
#include "uhub.h" #include "uhub.h"
/* Send MOTD, do logging etc */ static void log_user_login(struct user* u)
void on_login_success(struct user* u)
{ {
/* Logging - FIXME: Move this to a plugin */ const char* cred = get_user_credential_string(u->credentials);
const char* addr = ip_convert_to_string(&u->ipaddr); const char* addr = ip_convert_to_string(&u->ipaddr);
const char* credentials_string[] = { "!none!", "link", "guest", "user", "operator", "super", "admin" }; hub_log(log_user, "LoginOK %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, cred, u->user_agent);
}
static void log_user_login_error(struct user* u, enum status_message msg)
{
const char* addr = ip_convert_to_string(&u->ipaddr);
const char* message = hub_get_status_message_log(u->hub, msg);
hub_log(log_user, "LoginError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent);
}
static void log_user_logout(struct user* u, const char* message)
{
const char* addr = ip_convert_to_string(&u->ipaddr);
hub_log(log_user, "Logout %s/%s %s \"%s\" (%s)", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message);
}
static void log_user_nick_change(struct user* u, const char* nick)
{
const char* addr = ip_convert_to_string(&u->ipaddr);
hub_log(log_user, "NickChange %s/%s %s \"%s\" -> \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, nick);
}
/* Send MOTD, do logging etc */
void on_login_success(struct hub_info* hub, struct user* u)
{
struct timeval timeout = { TIMEOUT_IDLE, 0 }; struct timeval timeout = { TIMEOUT_IDLE, 0 };
/* Send user list of all existing users */ /* Send user list of all existing users */
if (!send_user_list(u)) if (!uman_send_user_list(u))
return; return;
/* Mark as being in the normal state, and add user to the user list */ /* Mark as being in the normal state, and add user to the user list */
user_set_state(u, state_normal); user_set_state(u, state_normal);
user_manager_add(u); uman_add(hub, u);
/* Print log message */ /* Print log message */
hub_log(log_user, "Login OK %s/%s \"%s\" [%s] (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, u->id.nick, addr, credentials_string[u->credentials], u->user_agent); log_user_login(u);
/* Announce new user to all connected users */ /* Announce new user to all connected users */
if (user_is_logged_in(u)) if (user_is_logged_in(u))
@@ -44,38 +68,31 @@ void on_login_success(struct user* u)
/* Send message of the day (if any) */ /* Send message of the day (if any) */
if (user_is_logged_in(u)) /* Previous send() can fail! */ if (user_is_logged_in(u)) /* Previous send() can fail! */
hub_send_motd(u); hub_send_motd(hub, u);
/* reset to idle timeout */ /* reset to idle timeout */
if (u->ev_read) if (u->ev_read)
event_add(u->ev_read, &timeout); event_add(u->ev_read, &timeout);
} }
void on_login_failure(struct hub_info* hub, struct user* u, enum status_message msg)
void on_login_failure(struct user* u, enum status_message msg)
{ {
const char* addr = ip_convert_to_string(&u->ipaddr); log_user_login_error(u, msg);
const char* message = hub_get_status_message(u->hub, msg); hub_send_status(hub, u, msg, status_level_fatal);
hub_log(log_user, "Login FAIL %s/%s \"%s\" [%s] (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, u->id.nick, addr, message, u->user_agent);
hub_send_status(u, msg, status_level_fatal);
user_disconnect(u, quit_logon_error); user_disconnect(u, quit_logon_error);
} }
void on_nick_change(struct hub_info* hub, struct user* u, const char* nick)
void on_nick_change(struct user* u, const char* nick)
{ {
if (user_is_logged_in(u)) if (user_is_logged_in(u))
{ {
hub_log(log_user, "Nick change %s/%s \"%s\" -> \"%s\"", sid_to_string(u->id.sid), u->id.cid, u->id.nick, nick); log_user_nick_change(u, nick);
} }
} }
void on_logout_user(struct hub_info* hub, struct user* user)
void on_logout_user(struct user* user)
{ {
const char* reason = ""; const char* reason = "";
const char* addr;
/* These are used for logging purposes */ /* These are used for logging purposes */
switch (user->quit_reason) switch (user->quit_reason)
@@ -90,18 +107,16 @@ void on_logout_user(struct user* user)
case quit_protocol_error: reason = "protocol error"; break; case quit_protocol_error: reason = "protocol error"; break;
case quit_logon_error: reason = "login error"; break; case quit_logon_error: reason = "login error"; break;
case quit_hub_disabled: reason = "hub disabled"; break; case quit_hub_disabled: reason = "hub disabled"; break;
case quit_ghost_timeout: reason = "ghost"; break;
default: default:
if (user->hub->status == hub_status_shutdown) if (hub->status == hub_status_shutdown)
reason = "hub shutdown"; reason = "hub shutdown";
else else
reason = "unknown error"; reason = "unknown error";
break; break;
} }
addr = ip_convert_to_string(&user->ipaddr); log_user_logout(user, reason);
hub_log(log_user, "Logout %s/%s \"%s\" [%s] (%s)", sid_to_string(user->id.sid), user->id.cid, user->id.nick, addr, reason);
user->quit_reason = 0; user->quit_reason = 0;
} }

View File

@@ -23,22 +23,22 @@
/** /**
* This event is triggered whenever a user successfully logs in to the hub. * This event is triggered whenever a user successfully logs in to the hub.
*/ */
extern void on_login_success(struct user* u); extern void on_login_success(struct hub_info* hub, struct 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 user* u, enum status_message msg); extern void on_login_failure(struct hub_info* hub, struct 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.
*/ */
extern void on_logout_user(struct user* u); extern void on_logout_user(struct hub_info* hub, struct user* u);
/** /**
* This event is triggered whenever a user changes his/her nickname. * This event is triggered whenever a user changes his/her nickname.
*/ */
extern void on_nick_change(struct user* u, const char* nick); extern void on_nick_change(struct hub_info* hub, struct user* u, const char* nick);
#endif /* HAVE_UHUB_HUB_EVENT_H */ #endif /* HAVE_UHUB_HUB_EVENT_H */

191
src/inf.c
View File

@@ -89,7 +89,7 @@ static int check_hash_tiger(const char* cid, const char* pid)
/* /*
* FIXME: Only works for tiger hash. If a client doesnt support tiger we cannot let it in! * FIXME: Only works for tiger hash. If a client doesnt support tiger we cannot let it in!
*/ */
static int check_cid(struct user* user, struct adc_message* cmd) static int check_cid(struct hub_info* hub, struct user* user, struct adc_message* cmd)
{ {
size_t pos; size_t pos;
char* cid = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID); char* cid = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID);
@@ -150,7 +150,7 @@ static int check_cid(struct user* user, struct adc_message* cmd)
} }
static int check_required_login_flags(struct user* user, struct adc_message* cmd) static int check_required_login_flags(struct hub_info* hub, struct user* user, struct adc_message* cmd)
{ {
int num = 0; int num = 0;
@@ -186,12 +186,12 @@ static int check_required_login_flags(struct user* user, struct adc_message* cmd
* 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 user* user, struct adc_message* cmd) int check_network(struct hub_info* hub, struct user* user, struct adc_message* cmd)
{ {
const char* address = ip_convert_to_string(&user->ipaddr); const char* address = ip_convert_to_string(&user->ipaddr);
/* Check for NAT override address */ /* Check for NAT override address */
if (acl_is_ip_nat_override(user->hub->acl, address)) if (acl_is_ip_nat_override(hub->acl, address))
{ {
char* client_given_ip = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR); char* client_given_ip = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
if (strcmp(client_given_ip, "0.0.0.0") != 0) if (strcmp(client_given_ip, "0.0.0.0") != 0)
@@ -222,6 +222,13 @@ int check_network(struct user* user, struct adc_message* cmd)
return 0; return 0;
} }
void strip_network(struct user* user, struct adc_message* cmd)
{
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_UDP_PORT);
}
static int nick_length_ok(const char* nick) static int nick_length_ok(const char* nick)
{ {
@@ -269,7 +276,7 @@ static int nick_is_utf8(const char* nick)
} }
static int check_nick(struct user* user, struct adc_message* cmd) static int check_nick(struct hub_info* hub, struct user* user, struct adc_message* cmd)
{ {
char* nick; char* nick;
char* tmp; char* tmp;
@@ -317,10 +324,10 @@ static int check_nick(struct user* user, struct adc_message* cmd)
} }
static int check_logged_in(struct user* user, struct adc_message* cmd) static int check_logged_in(struct hub_info* hub, struct user* user, struct adc_message* cmd)
{ {
struct user* lookup1 = get_user_by_nick(user->hub, user->id.nick); struct user* lookup1 = uman_get_user_by_nick(hub, user->id.nick);
struct user* lookup2 = get_user_by_cid(user->hub, user->id.cid); struct user* lookup2 = uman_get_user_by_cid(hub, user->id.cid);
if (lookup1 == user) if (lookup1 == user)
{ {
@@ -332,7 +339,7 @@ static int check_logged_in(struct user* user, struct adc_message* cmd)
if (lookup1 == lookup2) if (lookup1 == lookup2)
{ {
hub_log(log_debug, "check_logged_in: exact same user is logged in: %s", user->id.nick); hub_log(log_debug, "check_logged_in: exact same user is logged in: %s", user->id.nick);
user_disconnect(lookup1, quit_timeout); user_disconnect(lookup1, quit_ghost_timeout);
return 0; return 0;
} }
else else
@@ -358,7 +365,7 @@ static int check_logged_in(struct user* user, struct adc_message* cmd)
* But this is not something we want to do, and is deprecated in the ADC specification. * But this is not something we want to do, and is deprecated in the ADC specification.
* One should rather look at capabilities/features. * One should rather look at capabilities/features.
*/ */
static int check_user_agent(struct user* user, struct adc_message* cmd) static int check_user_agent(struct hub_info* hub, struct user* user, struct adc_message* cmd)
{ {
char* ua_encoded = 0; char* ua_encoded = 0;
char* ua = 0; char* ua = 0;
@@ -379,19 +386,19 @@ static int check_user_agent(struct user* user, struct adc_message* cmd)
} }
static int check_acl(struct user* user, struct adc_message* cmd) static int check_acl(struct hub_info* hub, struct user* user, struct adc_message* cmd)
{ {
if (acl_is_cid_banned(user->hub->acl, user->id.cid)) if (acl_is_cid_banned(hub->acl, user->id.cid))
{ {
return status_msg_ban_permanently; return status_msg_ban_permanently;
} }
if (acl_is_user_banned(user->hub->acl, user->id.nick)) if (acl_is_user_banned(hub->acl, user->id.nick))
{ {
return status_msg_ban_permanently; return status_msg_ban_permanently;
} }
if (acl_is_user_denied(user->hub->acl, user->id.nick)) if (acl_is_user_denied(hub->acl, user->id.nick))
{ {
return status_msg_inf_error_nick_restricted; return status_msg_inf_error_nick_restricted;
} }
@@ -399,7 +406,7 @@ static int check_acl(struct user* user, struct adc_message* cmd)
return 0; return 0;
} }
static int check_limits(struct user* user, struct adc_message* cmd) static int check_limits(struct hub_info* hub, struct user* user, struct adc_message* cmd)
{ {
char* arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_SIZE); char* arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_SIZE);
if (arg) if (arg)
@@ -410,8 +417,8 @@ static int check_limits(struct user* user, struct adc_message* cmd)
if (user_is_logged_in(user)) if (user_is_logged_in(user))
{ {
user->hub->users->shared_size -= user->limits.shared_size; hub->users->shared_size -= user->limits.shared_size;
user->hub->users->shared_size += shared_size; hub->users->shared_size += shared_size;
} }
user->limits.shared_size = shared_size; user->limits.shared_size = shared_size;
hub_free(arg); hub_free(arg);
@@ -427,8 +434,8 @@ static int check_limits(struct user* user, struct adc_message* cmd)
if (user_is_logged_in(user)) if (user_is_logged_in(user))
{ {
user->hub->users->shared_files -= user->limits.shared_files; hub->users->shared_files -= user->limits.shared_files;
user->hub->users->shared_files += shared_files; hub->users->shared_files += shared_files;
} }
user->limits.shared_files = shared_files; user->limits.shared_files = shared_files;
hub_free(arg); hub_free(arg);
@@ -480,37 +487,37 @@ static int check_limits(struct user* user, struct adc_message* cmd)
if (!user_is_protected(user)) if (!user_is_protected(user))
{ {
if (user->limits.shared_size < hub_get_min_share(user->hub) && hub_get_min_share(user->hub)) if (user->limits.shared_size < hub_get_min_share(hub) && hub_get_min_share(hub))
{ {
return status_msg_user_share_size_low; return status_msg_user_share_size_low;
} }
if (user->limits.shared_size > hub_get_max_share(user->hub) && hub_get_max_share(user->hub)) if (user->limits.shared_size > hub_get_max_share(hub) && hub_get_max_share(hub))
{ {
return status_msg_user_share_size_high; return status_msg_user_share_size_high;
} }
if ((user->limits.hub_count_user > hub_get_max_hubs_user(user->hub) && hub_get_max_hubs_user(user->hub)) || if ((user->limits.hub_count_user > hub_get_max_hubs_user(hub) && hub_get_max_hubs_user(hub)) ||
(user->limits.hub_count_registered > hub_get_max_hubs_reg(user->hub) && hub_get_max_hubs_reg(user->hub)) || (user->limits.hub_count_registered > hub_get_max_hubs_reg(hub) && hub_get_max_hubs_reg(hub)) ||
(user->limits.hub_count_operator > hub_get_max_hubs_op(user->hub) && hub_get_max_hubs_op(user->hub)) || (user->limits.hub_count_operator > hub_get_max_hubs_op(hub) && hub_get_max_hubs_op(hub)) ||
(user->limits.hub_count_total > hub_get_max_hubs_total(user->hub) && hub_get_max_hubs_total(user->hub))) (user->limits.hub_count_total > hub_get_max_hubs_total(hub) && hub_get_max_hubs_total(hub)))
{ {
return status_msg_user_hub_limit_high; return status_msg_user_hub_limit_high;
} }
if ((user->limits.hub_count_user < hub_get_min_hubs_user(user->hub) && hub_get_min_hubs_user(user->hub)) || if ((user->limits.hub_count_user < hub_get_min_hubs_user(hub) && hub_get_min_hubs_user(hub)) ||
(user->limits.hub_count_registered < hub_get_min_hubs_reg(user->hub) && hub_get_min_hubs_reg(user->hub)) || (user->limits.hub_count_registered < hub_get_min_hubs_reg(hub) && hub_get_min_hubs_reg(hub)) ||
(user->limits.hub_count_operator < hub_get_min_hubs_op(user->hub) && hub_get_min_hubs_op(user->hub))) (user->limits.hub_count_operator < hub_get_min_hubs_op(hub) && hub_get_min_hubs_op(hub)))
{ {
return status_msg_user_hub_limit_low; return status_msg_user_hub_limit_low;
} }
if (user->limits.upload_slots < hub_get_min_slots(user->hub) && hub_get_min_slots(user->hub)) if (user->limits.upload_slots < hub_get_min_slots(hub) && hub_get_min_slots(hub))
{ {
return status_msg_user_slots_low; return status_msg_user_slots_low;
} }
if (user->limits.upload_slots > hub_get_max_slots(user->hub) && hub_get_max_slots(user->hub)) if (user->limits.upload_slots > hub_get_max_slots(hub) && hub_get_max_slots(hub))
{ {
return status_msg_user_slots_high; return status_msg_user_slots_high;
} }
@@ -525,10 +532,10 @@ static int check_limits(struct user* user, struct adc_message* cmd)
* If the hub is configured to allow only registered users and the user * If the hub is configured to allow only registered users and the user
* is not recognized this will return 1. * is not recognized this will return 1.
*/ */
static int set_credentials(struct user* user, struct adc_message* cmd) static int set_credentials(struct hub_info* hub, struct user* user, struct adc_message* cmd)
{ {
int ret = 0; int ret = 0;
struct user_access_info* info = acl_get_access_info(user->hub->acl, user->id.nick); struct user_access_info* info = acl_get_access_info(hub->acl, user->id.nick);
if (info) if (info)
{ {
@@ -619,42 +626,13 @@ static int user_is_registered(struct user* user)
} }
void update_user_info(struct user* u, struct adc_message* cmd) static int check_is_hub_full(struct hub_info* hub, struct user* user)
{
char prefix[2];
char* argument;
size_t n = 0;
struct adc_message* cmd_new = adc_msg_copy(u->info);
if (!cmd_new)
{
/* FIXME: OOM! */
return;
}
argument = adc_msg_get_argument(cmd, n++);
while (argument)
{
if (strlen(argument) >= 2)
{
prefix[0] = argument[0];
prefix[1] = argument[1];
adc_msg_replace_named_argument(cmd_new, prefix, argument+2);
}
hub_free(argument);
argument = adc_msg_get_argument(cmd, n++);
}
user_set_info(u, cmd_new);
}
static int check_is_hub_full(struct user* user)
{ {
/* /*
* If hub is full, don't let users in, but we still want to allow * If hub is full, don't let users in, but we still want to allow
* operators and admins to enter the hub. * operators and admins to enter the hub.
*/ */
if (user->hub->config->max_users && user->hub->users->count >= user->hub->config->max_users && !user_is_protected(user)) if (hub->config->max_users && hub->users->count >= hub->config->max_users && !user_is_protected(user))
{ {
return 1; return 1;
} }
@@ -662,22 +640,15 @@ static int check_is_hub_full(struct user* user)
} }
static int check_registered_users_only(struct user* user) static int check_registered_users_only(struct hub_info* hub, struct user* user)
{ {
if (user->hub->config->registered_users_only && !user_is_registered(user)) if (hub->config->registered_users_only && !user_is_registered(user))
{ {
return 1; return 1;
} }
return 0; return 0;
} }
#define INF_CHECK(FUNC, USER, CMD) \
do { \
int ret = FUNC(USER, CMD); \
if (ret < 0) \
return ret; \
} while(0)
static int hub_handle_info_common(struct user* user, struct adc_message* cmd) static int hub_handle_info_common(struct user* user, struct adc_message* cmd)
{ {
/* Remove server restricted flags */ /* Remove server restricted flags */
@@ -689,9 +660,9 @@ static int hub_handle_info_common(struct user* user, struct adc_message* cmd)
return 0; return 0;
} }
static int hub_handle_info_low_bandwidth(struct user* user, struct adc_message* cmd) static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct user* user, struct adc_message* cmd)
{ {
if (user->hub->config->low_bandwidth_mode) if (hub->config->low_bandwidth_mode)
{ {
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_USER_AGENT); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_USER_AGENT);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES);
@@ -710,40 +681,54 @@ static int hub_handle_info_low_bandwidth(struct user* user, struct adc_message*
return 0; return 0;
} }
int hub_handle_info_login(struct user* user, struct adc_message* cmd) #define INF_CHECK(FUNC, HUB, USER, CMD) \
do { \
int ret = FUNC(HUB, USER, CMD); \
if (ret < 0) \
return ret; \
} while(0)
int hub_perform_login_checks(struct hub_info* hub, struct user* user, struct adc_message* cmd)
{
/* Make syntax checks. */
INF_CHECK(check_required_login_flags, hub, user, cmd);
INF_CHECK(check_cid, hub, user, cmd);
INF_CHECK(check_nick, hub, user, cmd);
INF_CHECK(check_network, hub, user, cmd);
INF_CHECK(check_user_agent, hub, user, cmd);
INF_CHECK(check_acl, hub, user, cmd);
INF_CHECK(check_logged_in, hub, user, cmd);
return 0;
}
int hub_handle_info_login(struct hub_info* hub, struct user* user, struct adc_message* cmd)
{ {
int need_auth = 0; int need_auth = 0;
/* Make syntax checks. */ INF_CHECK(hub_perform_login_checks, hub, user, cmd);
INF_CHECK(check_required_login_flags, user, cmd);
INF_CHECK(check_cid, user, cmd);
INF_CHECK(check_nick, user, cmd);
INF_CHECK(check_network, user, cmd);
INF_CHECK(check_user_agent, user, cmd);
INF_CHECK(check_acl, user, cmd);
INF_CHECK(check_logged_in, user, cmd);
/* Private ID must never be broadcasted - drop it! */ /* Private ID must never be broadcasted - drop it! */
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
/* FIXME: This needs some cleaning up */ /* FIXME: This needs some cleaning up */
need_auth = set_credentials(user, cmd); need_auth = set_credentials(hub, user, cmd);
/* Note: this must be done *after* set_credentials. */ /* Note: this must be done *after* set_credentials. */
if (check_is_hub_full(user)) if (check_is_hub_full(hub, user))
{ {
return status_msg_hub_full; return status_msg_hub_full;
} }
if (check_registered_users_only(user)) if (check_registered_users_only(hub, user))
{ {
return status_msg_hub_registered_users_only; return status_msg_hub_registered_users_only;
} }
INF_CHECK(check_limits, user, cmd); INF_CHECK(check_limits, hub, user, cmd);
/* strip off stuff if low_bandwidth_mode is enabled */ /* strip off stuff if low_bandwidth_mode is enabled */
hub_handle_info_low_bandwidth(user, cmd); hub_handle_info_low_bandwidth(hub, user, cmd);
/* Set initial user info */ /* Set initial user info */
user_set_info(user, cmd); user_set_info(user, cmd);
@@ -764,9 +749,9 @@ int hub_handle_info_login(struct user* user, struct adc_message* cmd)
* - CID/PID (valid, not taken, etc). * - CID/PID (valid, not taken, etc).
* - IP addresses (IPv4 and IPv6) * - IP addresses (IPv4 and IPv6)
*/ */
int hub_handle_info(struct user* user, const struct adc_message* cmd_unmodified) int hub_handle_info(struct hub_info* hub, struct user* user, const struct adc_message* cmd_unmodified)
{ {
struct adc_message* cmd = adc_msg_copy(cmd_unmodified); /* FIXME: Have a small memory leak here! */ struct adc_message* cmd = adc_msg_copy(cmd_unmodified);
if (!cmd) return -1; /* OOM */ if (!cmd) return -1; /* OOM */
cmd->priority = 1; cmd->priority = 1;
@@ -778,10 +763,20 @@ int hub_handle_info(struct user* user, const struct adc_message* cmd_unmodified)
*/ */
if (user_is_connecting(user)) if (user_is_connecting(user))
{ {
int ret = hub_handle_info_login(user, cmd); /*
* Don't allow the user to send multiple INF messages in this stage!
* Since that can have serious side-effects.
*/
if (user->info)
{
adc_msg_free(cmd);
return 0;
}
int ret = hub_handle_info_login(hub, user, cmd);
if (ret < 0) if (ret < 0)
{ {
on_login_failure(user, ret); on_login_failure(hub, user, ret);
adc_msg_free(cmd); adc_msg_free(cmd);
return -1; return -1;
} }
@@ -793,7 +788,7 @@ int hub_handle_info(struct user* user, const struct adc_message* cmd_unmodified)
post.id = UHUB_EVENT_USER_JOIN; post.id = UHUB_EVENT_USER_JOIN;
post.ptr = user; post.ptr = user;
post.flags = ret; /* 0 - all OK, 1 - need authentication */ post.flags = ret; /* 0 - all OK, 1 - need authentication */
event_queue_post(user->hub->queue, &post); event_queue_post(hub->queue, &post);
adc_msg_free(cmd); adc_msg_free(cmd);
return 0; return 0;
} }
@@ -811,15 +806,17 @@ int hub_handle_info(struct user* user, const struct adc_message* cmd_unmodified)
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_NICK)) if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_NICK))
{ {
#if ALLOW_CHANGE_NICK #if ALLOW_CHANGE_NICK
if (!check_nick(user, cmd)) if (!check_nick(hub, user, cmd))
#endif #endif
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK);
} }
/* FIXME - What if limits are not met ? */ /* FIXME - What if limits are not met ? */
check_limits(user, cmd); check_limits(hub, user, cmd);
hub_handle_info_low_bandwidth(user, cmd); strip_network(user, cmd);
update_user_info(user, cmd); hub_handle_info_low_bandwidth(hub, user, cmd);
user_update_info(user, cmd);
if (!adc_msg_is_empty(cmd)) if (!adc_msg_is_empty(cmd))
{ {

View File

@@ -47,7 +47,7 @@ enum nick_status
* *
* @return 0 on success, -1 on error * @return 0 on success, -1 on error
*/ */
extern int hub_handle_info(struct user* u, const struct adc_message* cmd); extern int hub_handle_info(struct hub_info* hub, struct user* u, const struct adc_message* cmd);
#endif /* HAVE_UHUB_INF_PARSER_H */ #endif /* HAVE_UHUB_INF_PARSER_H */

View File

@@ -177,8 +177,8 @@ void hub_log(int log_verbosity, const char *format, ...)
if (log_verbosity < verbosity) if (log_verbosity < verbosity)
{ {
t = time(NULL); t = time(NULL);
tmp = gmtime(&t); tmp = localtime(&t);
strftime(timestamp, 32, "%a, %d %b %Y %H:%M:%S +0000", tmp); strftime(timestamp, 32, "%Y-%m-%d %H:%M:%S", tmp);
va_start(args, format); va_start(args, format);
vsnprintf(logmsg, 1024, format, args); vsnprintf(logmsg, 1024, format, args);
va_end(args); va_end(args);

View File

@@ -37,47 +37,29 @@ void hub_handle_signal(int fd, short events, void* arg)
{ {
struct hub_info* hub = (struct hub_info*) arg; struct hub_info* hub = (struct hub_info*) arg;
int signal = fd; int signal = fd;
struct timeval now = {0, 0};
switch (signal) switch (signal)
{ {
case SIGINT: case SIGINT:
hub_log(log_info, "Interrupted. Shutting down..."); hub_log(log_info, "Interrupted. Shutting down...");
hub->status = hub_status_shutdown; hub->status = hub_status_shutdown;
event_loopexit(&now);
break; break;
case SIGTERM: case SIGTERM:
hub_log(log_info, "Terminated. Shutting down..."); hub_log(log_info, "Terminated. Shutting down...");
hub->status = hub_status_shutdown; hub->status = hub_status_shutdown;
event_loopexit(&now);
break; break;
case SIGPIPE: case SIGPIPE:
hub_log(log_trace, "hub_handle_signal(): caught SIGPIPE (ignoring)");
break; break;
case SIGHUP: case SIGHUP:
hub_log(log_info, "Caught hangup signal. Reloading configuration files...");
hub->status = hub_status_restart; hub->status = hub_status_restart;
event_loopexit(&now);
break;
case SIGUSR1:
hub_log(log_trace, "hub_handle_signal(): caught SIGUSR1 -- FIXME");
break;
case SIGUSR2:
hub_log(log_trace, "hub_handle_signal(): caught SIGUSR2");
{
user_manager_print_stats(hub);
}
break; break;
default: default:
hub_log(log_trace, "hub_handle_signal(): caught unknown signal: %d", signal); hub_log(log_trace, "hub_handle_signal(): caught unknown signal: %d", signal);
hub->status = hub_status_shutdown; hub->status = hub_status_shutdown;
event_loopexit(&now);
break; break;
} }
} }
@@ -89,8 +71,6 @@ static int signals[] =
SIGTERM, /* Terminate the application */ SIGTERM, /* Terminate the application */
SIGPIPE, /* prevent sigpipe from kills the application */ SIGPIPE, /* prevent sigpipe from kills the application */
SIGHUP, /* reload configuration */ SIGHUP, /* reload configuration */
SIGUSR1, /* dump statistics */
SIGUSR2, /* (unused) */
0 0
}; };
@@ -131,6 +111,12 @@ int main_loop()
do do
{ {
if (hub)
{
hub_log(log_info, "Reloading configuration files...");
hub_log(log_debug, "Hub status: %d", (int) hub->status);
}
if (read_config(arg_config, &configuration, !arg_have_config) == -1) if (read_config(arg_config, &configuration, !arg_have_config) == -1)
return -1; return -1;
@@ -183,9 +169,12 @@ int check_configuration(int dump)
int ret = read_config(arg_config, &configuration, 0); int ret = read_config(arg_config, &configuration, 0);
if (dump) if (dump)
{
if (ret != -1)
{ {
dump_config(&configuration, dump > 1); dump_config(&configuration, dump > 1);
puts(""); }
return 0;
} }
if (ret == -1) if (ret == -1)
@@ -193,6 +182,7 @@ int check_configuration(int dump)
fprintf(stderr, "ERROR\n"); fprintf(stderr, "ERROR\n");
return 1; return 1;
} }
fprintf(stdout, "OK\n"); fprintf(stdout, "OK\n");
return 0; return 0;
} }

View File

@@ -34,6 +34,7 @@
struct adc_message* adc_msg_incref(struct adc_message* msg) struct adc_message* adc_msg_incref(struct adc_message* msg)
{ {
if (!msg) return 0;
#ifndef ADC_MESSAGE_INCREF #ifndef ADC_MESSAGE_INCREF
msg->references++; msg->references++;
return msg; return msg;
@@ -264,6 +265,13 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
if (command == NULL) if (command == NULL)
return NULL; /* OOM */ return NULL; /* OOM */
if (!is_printable_utf8(line, length))
{
hub_log(log_debug, "Dropped message with non-printable UTF-8 characters.");
hub_free(command);
return NULL;
}
if (line[length-1] != '\n') if (line[length-1] != '\n')
{ {
need_terminate = 1; need_terminate = 1;

View File

@@ -31,6 +31,16 @@ int is_white_space(char c)
return 0; return 0;
} }
static int is_printable(unsigned char c)
{
if (c >= 32)
return 1;
if (c == '\t' || c == '\r' || c == '\n')
return 1;
return 0;
}
char* strip_white_space(char* string) char* strip_white_space(char* string)
{ {
@@ -48,17 +58,15 @@ char* strip_white_space(char* string)
return string; return string;
} }
static int is_valid_utf8_str(const char* string, size_t length)
int is_valid_utf8(const char* string)
{ {
int expect = 0; int expect = 0;
char div = 0; char div = 0;
int pos = 0; size_t pos = 0;
int length = strlen(string);
if (length == 0) return 1; if (length == 0) return 1;
for (pos = 0; pos < strlen(string); pos++) for (pos = 0; pos < length; pos++)
{ {
if (expect) if (expect)
{ {
@@ -74,13 +82,28 @@ int is_valid_utf8(const char* string)
if (string[pos] & div) expect++; if (string[pos] & div) expect++;
else break; else break;
} }
if ((string[pos] & div) || (pos+expect >= strlen(string))) return 0; if ((string[pos] & div) || (pos+expect >= length)) return 0;
} }
} }
} }
return 1; return 1;
} }
int is_valid_utf8(const char* string)
{
return is_valid_utf8_str(string, strlen(string));
}
int is_printable_utf8(const char* string, size_t length)
{
size_t pos = 0;
for (pos = 0; pos < length; pos++)
{
if (!is_printable(string[pos]))
return 0;
}
return is_valid_utf8_str(string, length);
}
int is_valid_base32_char(char c) int is_valid_base32_char(char c)
{ {

View File

@@ -26,6 +26,7 @@ extern int is_num(char c);
extern int is_space(char c); extern int is_space(char c);
extern int is_white_space(char c); extern int is_white_space(char c);
extern int is_valid_utf8(const char* string); extern int is_valid_utf8(const char* string);
extern int is_printable_utf8(const char* string, size_t length);
extern int is_valid_base32_char(char c); extern int is_valid_base32_char(char c);
extern void base32_encode(const unsigned char* buffer, size_t len, char* result); extern void base32_encode(const unsigned char* buffer, size_t len, char* result);
extern void base32_decode(const char* src, unsigned char* dst, size_t len); extern void base32_decode(const char* src, unsigned char* dst, size_t len);

View File

@@ -25,10 +25,9 @@ void net_on_read(int fd, short ev, void *arg)
static char buf[MAX_RECV_BUF]; static char buf[MAX_RECV_BUF];
struct user* user = (struct user*) arg; struct user* user = (struct user*) arg;
char* pos; char* pos;
char* start; size_t offset;
ssize_t offset; size_t buflen;
ssize_t size; ssize_t size;
ssize_t buflen;
int more = 1; int more = 1;
int flag_close = 0; int flag_close = 0;
@@ -43,7 +42,8 @@ void net_on_read(int fd, short ev, void *arg)
} }
else else
{ {
hub_send_ping(user); // FIXME: hub is not neccesarily set!
// hub_send_ping(hub, user);
} }
} }
@@ -55,10 +55,6 @@ void net_on_read(int fd, short ev, void *arg)
memcpy(buf, user->recv_buf, user->recv_buf_offset); memcpy(buf, user->recv_buf, user->recv_buf_offset);
offset = user->recv_buf_offset; offset = user->recv_buf_offset;
} }
else
{
offset = 0;
}
size = net_recv(fd, &buf[offset], MAX_RECV_BUF - offset, 0); size = net_recv(fd, &buf[offset], MAX_RECV_BUF - offset, 0);
if (size == -1) if (size == -1)
@@ -75,40 +71,64 @@ void net_on_read(int fd, short ev, void *arg)
else else
{ {
buflen = offset + size; buflen = offset + size;
start = buf; ssize_t handled = 0;
while ((pos = strchr(start, '\n')))
while ((pos = memchr(&buf[handled], '\n', (buflen - handled))))
{ {
pos[0] = '\0'; pos[0] = '\0';
if (*start && strlen(start) < user->hub->config->max_recv_buffer) size_t msglen = &pos[0] - &buf[handled];
if (user_flag_get(user, flag_maxbuf))
{ {
if (hub_handle_message(user, start, &pos[0]-&start[0]) == -1) user_flag_unset(user, flag_maxbuf);
}
else
{
if (msglen < user->hub->config->max_recv_buffer)
{
// FIXME: hub is not set????
if (hub_handle_message(user->hub, user, &buf[handled], msglen) == -1)
{ {
flag_close = quit_protocol_error; flag_close = quit_protocol_error;
more = 0; more = 0;
break; break;
} }
} }
start = &pos[1]; }
handled += msglen;
handled++;
} }
if (!more) break; if (handled == 0 && user_flag_get(user, flag_maxbuf))
handled = buflen;
if (&buf[offset + size] > &start[0]) if (!more)
break;
if (handled < buflen)
{
if ((buflen - handled) > user->hub->config->max_recv_buffer)
{
user_flag_set(user, flag_maxbuf);
hub_free(user->recv_buf);
user->recv_buf = 0;
user->recv_buf_offset = 0;
}
else
{ {
if (!user->recv_buf) if (!user->recv_buf)
{
user->recv_buf = hub_malloc(user->hub->config->max_recv_buffer); user->recv_buf = hub_malloc(user->hub->config->max_recv_buffer);
}
if (!user->recv_buf) if (user->recv_buf)
{
memcpy(user->recv_buf, &buf[handled], buflen - handled);
user->recv_buf_offset = buflen - handled;
}
else
{ {
flag_close = quit_memory_error; flag_close = quit_memory_error;
break; break;
} }
else
{
memcpy(user->recv_buf, start, &buf[offset + size] - &start[0]);
user->recv_buf_offset = &buf[offset + size] - &start[0];
} }
} }
else else
@@ -242,13 +262,13 @@ void net_on_accept(int server_fd, short ev, void *arg)
{ {
struct hub_info* hub = (struct hub_info*) arg; struct hub_info* hub = (struct hub_info*) arg;
struct user* user = 0; struct user* user = 0;
int accept_more = 1; struct ip_addr_encap ipaddr;
const char* addr; const char* addr;
struct timeval timeout = { TIMEOUT_CONNECTED, 0 }; struct timeval timeout = { TIMEOUT_CONNECTED, 0 };
while (accept_more) for (;;)
{ {
int fd = net_accept(server_fd); int fd = net_accept(server_fd, &ipaddr);
if (fd == -1) if (fd == -1)
{ {
if (net_error() == EWOULDBLOCK) if (net_error() == EWOULDBLOCK)
@@ -262,7 +282,7 @@ void net_on_accept(int server_fd, short ev, void *arg)
} }
} }
addr = net_get_peer_address(fd); addr = ip_convert_to_string(&ipaddr);
/* FIXME: Should have a plugin log this */ /* FIXME: Should have a plugin log this */
hub_log(log_trace, "Got connection from %s", addr); hub_log(log_trace, "Got connection from %s", addr);
@@ -284,7 +304,7 @@ void net_on_accept(int server_fd, short ev, void *arg)
} }
/* Store IP address in user object */ /* Store IP address in user object */
ip_convert_to_binary(addr, &user->ipaddr); memcpy(&user->ipaddr, &ipaddr, sizeof(ipaddr));
net_set_nonblocking(fd, 1); net_set_nonblocking(fd, 1);
net_set_nosigpipe(fd, 1); net_set_nosigpipe(fd, 1);
@@ -294,23 +314,6 @@ void net_on_accept(int server_fd, short ev, void *arg)
event_base_set(hub->evbase, user->ev_read); event_base_set(hub->evbase, user->ev_read);
event_base_set(hub->evbase, user->ev_write); event_base_set(hub->evbase, user->ev_write);
event_add(user->ev_read, &timeout); event_add(user->ev_read, &timeout);
} }
} }
#ifdef ADC_UDP_OPERATION
extern void net_on_packet(int fd, short ev, void *arg)
{
static char buffer[1024] = {0,};
// struct hub_info* hub = (struct hub_info*) arg;
// struct user* user = 0;
ssize_t size;
struct sockaddr_storage from;
socklen_t fromlen;
size = recvfrom(fd, buffer, 1024, 0, (struct sockaddr*) &from, &fromlen);
// FIXME: A plugin should handle this!
hub_log(log_info, "Datagram [%s] (%d bytes)", buffer, (int) size);
}
#endif

View File

@@ -40,13 +40,5 @@ extern void net_on_read_timeout(int fd, short ev, void* arg);
*/ */
extern void net_on_accept(int fd, short ev, void *arg); extern void net_on_accept(int fd, short ev, void *arg);
#ifdef ADC_UDP_OPERATION
/**
* Network callback to receive incoming UDP datagram.
*/
extern void net_on_packet(int fd, short ev, void *arg);
#endif
#endif /* HAVE_UHUB_NET_EVENT_H */ #endif /* HAVE_UHUB_NET_EVENT_H */

View File

@@ -236,13 +236,19 @@ int net_close(int fd)
} }
int net_accept(int fd) int net_accept(int fd, struct ip_addr_encap* ipaddr)
{ {
struct sockaddr_storage addr; struct sockaddr_storage addr;
struct sockaddr_in* addr4;
struct sockaddr_in6* addr6;
socklen_t addr_size; socklen_t addr_size;
int ret = 0; int ret = 0;
addr_size = sizeof(struct sockaddr_storage); addr_size = sizeof(struct sockaddr_storage);
memset(&addr, 0, addr_size); memset(&addr, 0, addr_size);
addr4 = (struct sockaddr_in*) &addr;
addr6 = (struct sockaddr_in6*) &addr;
ret = accept(fd, (struct sockaddr*) &addr, &addr_size); ret = accept(fd, (struct sockaddr*) &addr, &addr_size);
if (ret == -1) if (ret == -1)
@@ -270,6 +276,20 @@ int net_accept(int fd)
else else
{ {
net_stats_add_accept(); net_stats_add_accept();
if (ipaddr)
{
memset(ipaddr, 0, sizeof(struct ip_addr_encap));
ipaddr->af = addr4->sin_family;
if (ipaddr->af == AF_INET6)
{
memcpy(&ipaddr->internal_ip_data.in6, &addr6->sin6_addr, sizeof(struct in6_addr));
}
else
{
memcpy(&ipaddr->internal_ip_data.in, &addr4->sin_addr, sizeof(struct in_addr));
}
}
} }
return ret; return ret;
@@ -465,11 +485,9 @@ const char* net_get_peer_address(int fd)
name4 = (struct sockaddr_in*) &storage; name4 = (struct sockaddr_in*) &storage;
name = (struct sockaddr*) &storage; name = (struct sockaddr*) &storage;
int af = net_is_ipv6_supported() ? AF_INET6 : AF_INET;
if (getpeername(fd, (struct sockaddr*) name, &namelen) != -1) if (getpeername(fd, (struct sockaddr*) name, &namelen) != -1)
{ {
int af = name4->sin_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);

View File

@@ -83,8 +83,11 @@ extern int net_close(int fd);
/** /**
* A wrapper for the accept() function call. * A wrapper for the accept() function call.
* @param fd socket descriptor
* @param ipaddr (in/out) if non-NULL the ip address of the
* accepted peer is filled in.
*/ */
extern int net_accept(int fd); extern int net_accept(int fd, struct ip_addr_encap* ipaddr);
/** /**
* A wrapper for the connect() call. * A wrapper for the connect() call.

137
src/rbtree.c Normal file
View File

@@ -0,0 +1,137 @@
/*
* 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/>.
*
*/
#if 0
#include <sys/types.h>
#include "rbtree.h"
#define RED 0
#define BLACK 1
struct rb_node
{
const void* key;
const void* value; /* data */
int color;
struct rb_node* parent;
struct rb_node* left;
struct rb_node* right;
};
struct rb_tree
{
struct rb_node* root;
size_t elements;
rb_tree_alloc alloc;
rb_tree_free free;
rb_tree_compare compare;
};
/* returns the grandparent of a node, if it exits */
static inline struct rb_node* get_grandparent(struct rb_node* n)
{
if (n->parent)
return n->parent->parent;
return 0;
}
static struct rb_node* get_uncle(struct rb_node* n)
{
struct rb_node* gparent = n->parent ? n->parent->parent : 0;
if (gparent)
return (n->parent == gparent->left) ? gparent->right : gparent->left;
return 0;
}
static struct rb_node* tree_search(struct rb_tree* tree, const void* key)
{
struct rb_node* node = tree->root;
while (node)
{
int res = tree->compare(key, node->key);
if (res < 0) node = node->left;
else if (res > 0) node = node->right;
else return node;
}
return 0;
}
static struct rb_node* tree_insert(struct rb_tree* tree, const void* key, const void* value)
{
struct rb_node* node = tree->root;
struct rb_node* newnode = tree->alloc(sizeof(struct rb_node));
newnode->key = key;
newnode->value = value;
newnode->color = RED;
while (node)
{
int res = tree->compare(key, node->key);
if (res < 0) node = node->left;
else if (res > 0) node = node->right;
else
{
/* key already exists in tree */
return node;
}
}
return newnode;
}
struct rb_tree* rb_tree_create(rb_tree_compare compare, rb_tree_alloc a, rb_tree_free f)
{
struct rb_tree* tree = a(sizeof(struct rb_tree));
tree->compare = compare;
tree->alloc = a;
tree->free = f;
return tree;
}
void rb_tree_destroy(struct rb_tree* tree)
{
rb_tree_free f = tree->free;
f(tree);
}
void* rb_tree_insert(struct rb_tree* tree, const void* key, const void* value)
{
struct rb_node* node = tree_insert(tree, key, value);
if (node)
return (void*) node->value;
return 0;
}
void* rb_tree_remove(struct rb_tree* tree, const void* key)
{
}
void* rb_tree_get(struct rb_tree* tree, const void* key)
{
struct rb_node* node = tree_search(tree, key);
if (node)
return node->value;
return 0;
}
#endif

38
src/rbtree.h Normal file
View File

@@ -0,0 +1,38 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HAVE_UHUB_RED_BLACK_TREE_H
#define HAVE_UHUB_RED_BLACK_TREE_H
struct rb_tree;
typedef int (*rb_tree_compare)(const void* a, const void* b);
typedef void* (*rb_tree_alloc)(size_t);
typedef void (*rb_tree_free)(void*);
extern struct rb_tree* rb_tree_create(rb_tree_compare, rb_tree_alloc, rb_tree_free);
extern void rb_tree_destroy(struct rb_tree*);
extern void* rb_tree_insert(struct rb_tree* tree, const void* key, const void* data);
extern void* rb_tree_remove(struct rb_tree* tree, const void* key);
extern void* rb_tree_get(struct rb_tree* tree, const void* key);
#endif /* HAVE_UHUB_RED_BLACK_TREE_H */

View File

@@ -31,7 +31,7 @@ int route_message(struct user* u, struct adc_message* msg)
break; break;
case 'D': case 'D':
target = get_user_by_sid(u->hub, msg->target); target = uman_get_user_by_sid(u->hub, msg->target);
if (target) if (target)
{ {
route_to_user(target, msg); route_to_user(target, msg);
@@ -39,7 +39,7 @@ int route_message(struct user* u, struct adc_message* msg)
break; break;
case 'E': case 'E':
target = get_user_by_sid(u->hub, msg->target); target = uman_get_user_by_sid(u->hub, msg->target);
if (target) if (target)
{ {
route_to_user(target, msg); route_to_user(target, msg);

View File

@@ -115,12 +115,51 @@ void user_set_info(struct user* user, struct adc_message* cmd)
user->info = adc_msg_incref(cmd); user->info = adc_msg_incref(cmd);
} }
void user_update_info(struct user* u, struct adc_message* cmd)
{
char prefix[2];
char* argument;
size_t n = 0;
struct adc_message* cmd_new = adc_msg_copy(u->info);
if (!cmd_new)
{
/* FIXME: OOM! */
return;
}
/*
* FIXME: Optimization potential:
*
* remove parts of cmd that do not really change anything in cmd_new.
* this can save bandwidth if clients send multiple updates for information
* that does not really change anything.
*/
argument = adc_msg_get_argument(cmd, n++);
while (argument)
{
if (strlen(argument) >= 2)
{
prefix[0] = argument[0];
prefix[1] = argument[1];
adc_msg_replace_named_argument(cmd_new, prefix, argument+2);
}
hub_free(argument);
argument = adc_msg_get_argument(cmd, n++);
}
user_set_info(u, cmd_new);
adc_msg_free(cmd_new);
}
static int convert_support_fourcc(int fourcc) static int convert_support_fourcc(int fourcc)
{ {
switch (fourcc) switch (fourcc)
{ {
case FOURCC('B','A','S','0'): /* Obsolete */ case FOURCC('B','A','S','0'): /* Obsolete */
#ifndef OLD_ADC_SUPPORT
return 0;
#endif
case FOURCC('B','A','S','E'): case FOURCC('B','A','S','E'):
return feature_base; return feature_base;

View File

@@ -47,11 +47,12 @@ 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) */
flag_ignore = 0x01000000, /** Ignore further reads */ flag_ignore = 0x01000000, /** Ignore further reads */
flag_choke = 0x02000000, /** Choked: Cannot send, waiting for write event */ flag_maxbuf = 0x02000000, /** Hit max buf read, ignore msg */
flag_want_read = 0x04000000, /** Need to read (SSL) */ flag_choke = 0x04000000, /** Choked: Cannot send, waiting for write event */
flag_want_write = 0x08000000, /** Need to write (SSL) */ flag_want_read = 0x08000000, /** Need to read (SSL) */
flag_user_list = 0x10000000, /** Send queue bypass (when receiving the send queue) */ flag_want_write = 0x10000000, /** Need to write (SSL) */
flag_nat = 0x20000000, /** nat override enabled */ flag_user_list = 0x20000000, /** Send queue bypass (when receiving the send queue) */
flag_nat = 0x40000000, /** nat override enabled */
}; };
@@ -68,6 +69,7 @@ enum user_quit_reason
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_hub_disabled = 10, /** Hub is disabled. No new connections allowed */
quit_ghost_timeout = 11, /** The user is a ghost, and trying to login from another connection */
}; };
@@ -169,9 +171,18 @@ extern void user_disconnect(struct user* user, int reason);
* This associates a INF message to the user. * This associates a INF message to the user.
* If the user already has a INF message associated, then this is * If the user already has a INF message associated, then this is
* released before setting the new one. * released before setting the new one.
*
* @param info new inf message (can be NULL)
*/ */
extern void user_set_info(struct user* user, struct adc_message* info); extern void user_set_info(struct user* user, struct adc_message* info);
/**
* Update a user's INF message.
* Will parse replace all ellements in the user's inf message with
* the parameters from the cmd (merge operation).
*/
extern void user_update_info(struct user* user, struct adc_message* cmd);
/** /**
* Specify a user's state. * Specify a user's state.
* NOTE: DON'T, unless you know what you are doing. * NOTE: DON'T, unless you know what you are doing.

View File

@@ -21,7 +21,7 @@
/* /*
* 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 user_manager_shutdown(). * Should only be used in uman_shutdown().
*/ */
static void clear_user_list_callback(void* ptr) static void clear_user_list_callback(void* ptr)
{ {
@@ -39,7 +39,7 @@ static void clear_user_list_callback(void* ptr)
} }
void user_manager_update_stats(struct hub_info* hub) void uman_update_stats(struct hub_info* hub)
{ {
const int factor = TIMEOUT_STATS; const int factor = TIMEOUT_STATS;
struct net_statistics* total; struct net_statistics* total;
@@ -57,7 +57,7 @@ void user_manager_update_stats(struct hub_info* hub)
} }
void user_manager_print_stats(struct hub_info* hub) void uman_print_stats(struct hub_info* hub)
{ {
hub_log(log_info, "Statistics users=%zu (peak_users=%zu), net_tx=%d KB/s, net_rx=%d KB/s (peak_tx=%d KB/s, peak_rx=%d KB/s)", hub_log(log_info, "Statistics users=%zu (peak_users=%zu), net_tx=%d KB/s, net_rx=%d KB/s (peak_tx=%d KB/s, peak_rx=%d KB/s)",
hub->users->count, hub->users->count,
@@ -68,23 +68,31 @@ void user_manager_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(int fd, short ev, void *arg) 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*) arg;
struct timeval timeout = { TIMEOUT_STATS, 0 }; struct timeval timeout = { TIMEOUT_STATS, 0 };
user_manager_update_stats(hub); uman_update_stats(hub);
evtimer_set(&hub->ev_timer, timer_statistics, hub); evtimer_set(&hub->ev_timer, timer_statistics, hub);
event_base_set(hub->evbase, &hub->ev_timer); event_base_set(hub->evbase, &hub->ev_timer);
evtimer_add(&hub->ev_timer, &timeout); evtimer_add(&hub->ev_timer, &timeout);
} }
#endif
int user_manager_init(struct hub_info* hub) int uman_init(struct hub_info* hub)
{ {
struct user_manager* users = NULL; struct user_manager* users = NULL;
#ifdef USERMANAGER_TIMER
struct timeval timeout = { TIMEOUT_STATS, 0 }; struct timeval timeout = { TIMEOUT_STATS, 0 };
#endif
if (!hub)
return -1;
users = (struct user_manager*) hub_malloc_zero(sizeof(struct user_manager)); users = (struct user_manager*) hub_malloc_zero(sizeof(struct user_manager));
if (!users)
return -1;
users->list = list_create(); users->list = list_create();
users->free_sid = 1; users->free_sid = 1;
@@ -97,45 +105,73 @@ int user_manager_init(struct hub_info* hub)
hub->users = users; hub->users = users;
#ifdef USERMANAGER_TIMER
evtimer_set(&hub->ev_timer, timer_statistics, hub); evtimer_set(&hub->ev_timer, timer_statistics, hub);
event_base_set(hub->evbase, &hub->ev_timer); event_base_set(hub->evbase, &hub->ev_timer);
evtimer_add(&hub->ev_timer, &timeout); evtimer_add(&hub->ev_timer, &timeout);
#endif // 0
return 0; return 0;
} }
void user_manager_shutdown(struct hub_info* hub) int uman_shutdown(struct hub_info* hub)
{ {
struct user_manager* users = hub->users; if (!hub || !hub->users)
return -1;
#ifdef USERMANAGER_TIMER
event_del(&hub->ev_timer); event_del(&hub->ev_timer);
#endif
list_clear(users->list, &clear_user_list_callback); if (hub->users->list)
list_destroy(users->list); {
list_clear(hub->users->list, &clear_user_list_callback);
list_destroy(hub->users->list);
}
hub_free(hub->users); hub_free(hub->users);
hub->users = 0;
return 0;
} }
void user_manager_add(struct user* user) int uman_add(struct hub_info* hub, struct user* user)
{ {
list_append(user->hub->users->list, user); if (!hub || !user)
user->hub->users->count++; return -1;
user->hub->users->count_peak = MAX(user->hub->users->count, user->hub->users->count_peak);
user->hub->users->shared_size += user->limits.shared_size; if (user->hub)
user->hub->users->shared_files += user->limits.shared_files; return -1;
list_append(hub->users->list, user);
hub->users->count++;
hub->users->count_peak = MAX(hub->users->count, hub->users->count_peak);
hub->users->shared_size += user->limits.shared_size;
hub->users->shared_files += user->limits.shared_files;
user->hub = hub;
return 0;
} }
void user_manager_remove(struct user* user) int uman_remove(struct hub_info* hub, struct user* user)
{ {
list_remove(user->hub->users->list, user); if (!hub || !user)
user->hub->users->count--; return -1;
user->hub->users->shared_size -= user->limits.shared_size; list_remove(hub->users->list, user);
user->hub->users->shared_files -= user->limits.shared_files; hub->users->count--;
hub->users->shared_size -= user->limits.shared_size;
hub->users->shared_files -= user->limits.shared_files;
user->hub = 0;
return 0;
} }
struct user* get_user_by_sid(struct hub_info* hub, sid_t sid) struct user* uman_get_user_by_sid(struct hub_info* hub, sid_t sid)
{ {
struct user* user = (struct user*) list_get_first(hub->users->list); /* iterate users */ struct user* user = (struct user*) list_get_first(hub->users->list); /* iterate users */
while (user) while (user)
@@ -148,7 +184,7 @@ struct user* get_user_by_sid(struct hub_info* hub, sid_t sid)
} }
struct user* get_user_by_cid(struct hub_info* hub, const char* cid) struct user* uman_get_user_by_cid(struct hub_info* hub, const char* cid)
{ {
struct user* user = (struct user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */ struct user* user = (struct user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
while (user) while (user)
@@ -161,7 +197,7 @@ struct user* get_user_by_cid(struct hub_info* hub, const char* cid)
} }
struct user* get_user_by_nick(struct hub_info* hub, const char* nick) struct user* uman_get_user_by_nick(struct hub_info* hub, const char* nick)
{ {
struct user* user = (struct user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */ struct user* user = (struct user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
while (user) while (user)
@@ -174,7 +210,7 @@ struct user* get_user_by_nick(struct hub_info* hub, const char* nick)
} }
int send_user_list(struct user* target) int uman_send_user_list(struct user* target)
{ {
int ret = 1; int ret = 1;
user_flag_set(target, flag_user_list); user_flag_set(target, flag_user_list);
@@ -198,7 +234,7 @@ int send_user_list(struct user* target)
} }
void send_quit_message(struct user* leaving) void uman_send_quit_message(struct user* leaving)
{ {
struct adc_message* command = adc_msg_construct(ADC_CMD_IQUI, 6); struct adc_message* command = adc_msg_construct(ADC_CMD_IQUI, 6);
adc_msg_add_argument(command, (const char*) sid_to_string(leaving->id.sid)); adc_msg_add_argument(command, (const char*) sid_to_string(leaving->id.sid));
@@ -213,7 +249,7 @@ void send_quit_message(struct user* leaving)
} }
sid_t user_manager_get_free_sid(struct hub_info* hub) sid_t uman_get_free_sid(struct hub_info* hub)
{ {
#if 0 #if 0
struct user* user; struct user* user;

View File

@@ -34,55 +34,70 @@ struct user_manager
* Initializes the user manager. * Initializes the user manager.
* @return 0 on success, or -1 if error (out of memory). * @return 0 on success, or -1 if error (out of memory).
*/ */
extern int user_manager_init(struct hub_info* hub); extern int uman_init(struct hub_info* hub);
/** /**
* Shuts down the user manager. * Shuts down the user manager.
* All users will be disconnected and deleted as part of this. * All users will be disconnected and deleted as part of this.
*
* @return 0 on success, or -1 in an error occured (hub is invalid).
*/ */
extern void user_manager_shutdown(struct hub_info* hub); extern int uman_shutdown(struct hub_info* hub);
/** /**
* Generate statistics for logfiles. * Generate statistics for logfiles.
*/ */
extern void user_manager_update_stats(struct hub_info* hub); extern void uman_update_stats(struct hub_info* hub);
extern void user_manager_print_stats(struct hub_info* hub); extern void uman_print_stats(struct hub_info* hub);
/** /**
* Add a new user to the user manager. * Add a user to the user manager.
*
* @param hub The hub to add the user to
* @param user The user to be added to the hub.
*/ */
extern void user_manager_add(struct user* user); extern int uman_add(struct hub_info* hub, struct user* user);
/** /**
* Remove a user from the user manager. * Remove a user from the user manager.
* This user is connected, and will be moved to the leaving queue, pending * This user is connected, and will be moved to the leaving queue, pending
* all messages in the message queue, and resource cleanup. * all messages in the message queue, and resource cleanup.
*
* @return 0 if successfully removed, -1 if error.
*/ */
extern void user_manager_remove(struct user* user); extern int uman_remove(struct hub_info* hub, struct user* user);
/** /**
* Returns a free sid for a new user. * Returns and allocates an unused session ID (SID).
*/ */
extern sid_t user_manager_get_free_sid(struct hub_info* hub); extern sid_t uman_get_free_sid(struct hub_info* hub);
/** /**
* Lookup a user based on the session ID (sid). * Lookup a user based on the session ID (SID).
* NOTE: This will only search connected users. *
* NOTE: This function will only search connected users, which means
* that SIDs assigned to users who are not yet completely logged in,
* or are in the process of being disconnected will result in this
* function returning NULL even though the sid is not freely available.
*
* FIXME: Is that really safe / sensible ?
* - Makes sense from a message routing point of view.
*
* @return a user if found, or NULL if not found * @return a user if found, or NULL if not found
*/ */
extern struct user* get_user_by_sid(struct hub_info* hub, sid_t sid); extern struct user* uman_get_user_by_sid(struct hub_info* hub, sid_t sid);
/** /**
* Lookup a user based on the client ID (cid). * Lookup a user based on the client ID (CID).
* @return a user if found, or NULL if not found * @return a user if found, or NULL if not found
*/ */
extern struct user* get_user_by_cid(struct hub_info* hub, const char* cid); extern struct user* uman_get_user_by_cid(struct hub_info* hub, const char* cid);
/** /**
* Lookup a user based on the nick name. * Lookup a user based on the nick name.
* @return a user if found, or NULL if not found * @return a user if found, or NULL if not found
*/ */
extern struct user* get_user_by_nick(struct hub_info* hub, const char* nick); extern struct user* uman_get_user_by_nick(struct hub_info* hub, const char* nick);
/** /**
* Send the user list of connected clients to 'user'. * Send the user list of connected clients to 'user'.
@@ -90,13 +105,13 @@ extern struct user* get_user_by_nick(struct hub_info* hub, const char* nick);
* *
* @return 1 if sending the user list succeeded, 0 otherwise. * @return 1 if sending the user list succeeded, 0 otherwise.
*/ */
extern int send_user_list(struct user* user); extern int uman_send_user_list(struct user* user);
/** /**
* Send a quit message to all connected users when 'user' is * Send a quit message to all connected users when 'user' is
* leaving the hub (for whatever reason). * leaving the hub (for whatever reason).
*/ */
extern void send_quit_message(struct user* user); extern void uman_send_quit_message(struct user* user);
#endif /* HAVE_UHUB_USER_MANAGER_H */ #endif /* HAVE_UHUB_USER_MANAGER_H */

View File

@@ -7,7 +7,7 @@
#endif #endif
#ifndef VERSION #ifndef VERSION
#define VERSION "0.2.7-alpha" #define VERSION "0.2.9-rc1"
#endif #endif
#ifndef COPYRIGHT #ifndef COPYRIGHT