Compare commits
52 Commits
0.3.1-rc1
...
plugin_wor
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa26052479 | ||
|
|
ccaa4860b4 | ||
|
|
7218011449 | ||
|
|
baeba01835 | ||
|
|
07d4e4470c | ||
|
|
ed53034ad5 | ||
|
|
fc8965f1c5 | ||
|
|
b3ed3a5526 | ||
|
|
1480b7e9c0 | ||
|
|
50fde1c5c8 | ||
|
|
77faac0494 | ||
|
|
473ff0e159 | ||
|
|
62333c5f39 | ||
|
|
44860c8477 | ||
|
|
c70119870a | ||
|
|
b29f34af4a | ||
|
|
076492f1b9 | ||
|
|
b6fb2b41bd | ||
|
|
c82f8ba167 | ||
|
|
6c9cd4ca50 | ||
|
|
201acad409 | ||
|
|
51c5b6169c | ||
|
|
b7e62b46cc | ||
|
|
321cddad8e | ||
|
|
8ec55a59f5 | ||
|
|
d3ebc409cb | ||
|
|
2fa5c01050 | ||
|
|
45462595ac | ||
|
|
0a3fe10f16 | ||
|
|
8e816fd196 | ||
|
|
88a22659a1 | ||
|
|
3393ee6a85 | ||
|
|
58630fde08 | ||
|
|
8815118fde | ||
|
|
5454ae279a | ||
|
|
8e579f4601 | ||
|
|
e220357176 | ||
|
|
8bed952022 | ||
|
|
c4604a7e94 | ||
|
|
236daeae53 | ||
|
|
862c6a1baf | ||
|
|
198d86a1ee | ||
|
|
2ded9f3e09 | ||
|
|
59ed268f4d | ||
|
|
963416ad73 | ||
|
|
29c162727c | ||
|
|
1ce258bccf | ||
|
|
0de66286fa | ||
|
|
1a98bb6810 | ||
|
|
5e6879dffb | ||
|
|
1b56adb8c0 | ||
|
|
685597c795 |
12
ChangeLog
12
ChangeLog
@@ -1,3 +1,15 @@
|
|||||||
|
0.3.1:
|
||||||
|
- Fixed bug where !getip did not work.
|
||||||
|
- Added flood control configuration options.
|
||||||
|
- Added configuration options to disallow old/obsolete ADC clients.
|
||||||
|
- Fixed crash bugs, an freezes.
|
||||||
|
- SSL/TLS fix for tls_require configuration option.
|
||||||
|
- Fixed disconnect messages, so that clients can interpret them.
|
||||||
|
- Fixed bugs where share limits could be circumvented.
|
||||||
|
- Added support for listening to multiple ports.
|
||||||
|
- kqueue backend for Mac OS X, and BSD systems.
|
||||||
|
|
||||||
|
|
||||||
0.3.0:
|
0.3.0:
|
||||||
- More user commands: ban, broadcast, mute, rules, history, myip, whoip, log
|
- More user commands: ban, broadcast, mute, rules, history, myip, whoip, log
|
||||||
- Experimental SSL support
|
- Experimental SSL support
|
||||||
|
|||||||
50
GNUmakefile
50
GNUmakefile
@@ -3,6 +3,8 @@
|
|||||||
## Copyright (C) 2007-2010, Jan Vidar Krey <janvidar@extatic.org>
|
## Copyright (C) 2007-2010, Jan Vidar Krey <janvidar@extatic.org>
|
||||||
#
|
#
|
||||||
|
|
||||||
|
-include Makefile.private
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
LD := $(CC)
|
LD := $(CC)
|
||||||
MV := mv
|
MV := mv
|
||||||
@@ -10,6 +12,7 @@ RANLIB := ranlib
|
|||||||
CFLAGS += -pipe -Wall
|
CFLAGS += -pipe -Wall
|
||||||
USE_SSL ?= NO
|
USE_SSL ?= NO
|
||||||
USE_BIGENDIAN ?= AUTO
|
USE_BIGENDIAN ?= AUTO
|
||||||
|
USE_PLUGINS ?= YES
|
||||||
BITS ?= AUTO
|
BITS ?= AUTO
|
||||||
SILENT ?= YES
|
SILENT ?= YES
|
||||||
TERSE ?= NO
|
TERSE ?= NO
|
||||||
@@ -40,6 +43,7 @@ UHUB_PREFIX ?= c:/uhub/
|
|||||||
CFLAGS += -mno-cygwin
|
CFLAGS += -mno-cygwin
|
||||||
LDFLAGS += -mno-cygwin
|
LDFLAGS += -mno-cygwin
|
||||||
BIN_EXT ?= .exe
|
BIN_EXT ?= .exe
|
||||||
|
USE_PLUGINS := NO
|
||||||
else
|
else
|
||||||
DESTDIR ?= /
|
DESTDIR ?= /
|
||||||
UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub
|
UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub
|
||||||
@@ -116,7 +120,13 @@ CFLAGS += -DSSL_SUPPORT
|
|||||||
LDLIBS += -lssl
|
LDLIBS += -lssl
|
||||||
endif
|
endif
|
||||||
|
|
||||||
GIT_VERSION=$(shell git describe 2>/dev/null || echo "")
|
ifeq ($(USE_PLUGINS),YES)
|
||||||
|
CFLAGS += -DPLUGIN_SUPPORT
|
||||||
|
LDLIBS += -ldl
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
GIT_VERSION=$(shell git describe --tags 2>/dev/null || echo "")
|
||||||
GIT_REVISION=$(shell git show --abbrev-commit 2>/dev/null | head -n 1 | cut -f 2 -d " " || echo "")
|
GIT_REVISION=$(shell git show --abbrev-commit 2>/dev/null | head -n 1 | cut -f 2 -d " " || echo "")
|
||||||
OLD_REVISION=$(shell grep GIT_REVISION revision.h 2>/dev/null | cut -f 3 -d " " | tr -d "\"")
|
OLD_REVISION=$(shell grep GIT_REVISION revision.h 2>/dev/null | cut -f 3 -d " " | tr -d "\"")
|
||||||
|
|
||||||
@@ -126,6 +136,7 @@ libuhub_SOURCES := \
|
|||||||
src/core/commands.c \
|
src/core/commands.c \
|
||||||
src/core/config.c \
|
src/core/config.c \
|
||||||
src/core/eventqueue.c \
|
src/core/eventqueue.c \
|
||||||
|
src/core/floodctl.c \
|
||||||
src/core/hub.c \
|
src/core/hub.c \
|
||||||
src/core/hubevent.c \
|
src/core/hubevent.c \
|
||||||
src/core/hubio.c \
|
src/core/hubio.c \
|
||||||
@@ -135,6 +146,8 @@ libuhub_SOURCES := \
|
|||||||
src/core/route.c \
|
src/core/route.c \
|
||||||
src/core/user.c \
|
src/core/user.c \
|
||||||
src/core/usermanager.c \
|
src/core/usermanager.c \
|
||||||
|
src/core/plugininvoke.c \
|
||||||
|
src/core/pluginloader.c \
|
||||||
src/network/backend.c \
|
src/network/backend.c \
|
||||||
src/network/connection.c \
|
src/network/connection.c \
|
||||||
src/network/epoll.c \
|
src/network/epoll.c \
|
||||||
@@ -165,19 +178,28 @@ adcrush_SOURCES := src/tools/adcrush.c
|
|||||||
admin_SOURCES := src/tools/admin.c
|
admin_SOURCES := src/tools/admin.c
|
||||||
|
|
||||||
autotest_SOURCES := \
|
autotest_SOURCES := \
|
||||||
autotest/test_message.tcc \
|
autotest/test_eventqueue.tcc \
|
||||||
|
autotest/test_hub.tcc \
|
||||||
|
autotest/test_inf.tcc \
|
||||||
|
autotest/test_ipfilter.tcc \
|
||||||
autotest/test_list.tcc \
|
autotest/test_list.tcc \
|
||||||
autotest/test_memory.tcc \
|
autotest/test_memory.tcc \
|
||||||
autotest/test_ipfilter.tcc \
|
autotest/test_message.tcc \
|
||||||
autotest/test_inf.tcc \
|
|
||||||
autotest/test_hub.tcc \
|
|
||||||
autotest/test_misc.tcc \
|
autotest/test_misc.tcc \
|
||||||
|
autotest/test_sid.tcc \
|
||||||
autotest/test_tiger.tcc \
|
autotest/test_tiger.tcc \
|
||||||
autotest/test_usermanager.tcc \
|
autotest/test_timer.tcc \
|
||||||
autotest/test_eventqueue.tcc
|
autotest/test_usermanager.tcc
|
||||||
|
|
||||||
autotest_OBJECTS = autotest.o
|
autotest_OBJECTS = autotest.o
|
||||||
|
|
||||||
|
plugin_example_SOURCES := src/plugins/mod_example.c
|
||||||
|
plugin_example_TARGET := $(plugin_example_SOURCES:.c=.so)
|
||||||
|
|
||||||
|
plugin_logging_SOURCES := src/plugins/mod_logging.c
|
||||||
|
plugin_logging_TARGET := $(plugin_example_SOURCES:.c=.so)
|
||||||
|
|
||||||
|
|
||||||
# Source to objects
|
# Source to objects
|
||||||
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
|
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
|
||||||
libadc_client_OBJECTS := $(libadc_client_SOURCES:.c=.o)
|
libadc_client_OBJECTS := $(libadc_client_SOURCES:.c=.o)
|
||||||
@@ -188,14 +210,23 @@ adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
|
|||||||
admin_OBJECTS := $(admin_SOURCES:.c=.o)
|
admin_OBJECTS := $(admin_SOURCES:.c=.o)
|
||||||
|
|
||||||
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS) $(admin_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS) $(admin_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
||||||
|
all_plugins := $(plugin_example_TARGET) $(plugin_logging_TARGET)
|
||||||
|
|
||||||
uhub_BINARY=uhub$(BIN_EXT)
|
uhub_BINARY=uhub$(BIN_EXT)
|
||||||
adcrush_BINARY=adcrush$(BIN_EXT)
|
adcrush_BINARY=adcrush$(BIN_EXT)
|
||||||
admin_BINARY=uhub-admin$(BIN_EXT)
|
admin_BINARY=uhub-admin$(BIN_EXT)
|
||||||
autotest_BINARY=autotest/test$(BIN_EXT)
|
autotest_BINARY=autotest/test$(BIN_EXT)
|
||||||
|
|
||||||
|
ifeq ($(USE_PLUGINS),YES)
|
||||||
|
all_OBJECTS += $(plugins)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
.PHONY: revision.h.tmp
|
.PHONY: revision.h.tmp
|
||||||
|
|
||||||
|
%.so: %.c
|
||||||
|
$(MSG_CC) $(CC) -shared -fPIC -o $@ $< $(CFLAGS)
|
||||||
|
|
||||||
%.o: %.c version.h revision.h
|
%.o: %.c version.h revision.h
|
||||||
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@ $<
|
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
@@ -222,7 +253,8 @@ revision.h.tmp:
|
|||||||
version.h: revision.h
|
version.h: revision.h
|
||||||
|
|
||||||
revision.h: revision.h.tmp
|
revision.h: revision.h.tmp
|
||||||
@if [ '$(GIT_REVISION)' != '$(OLD_REVISION)' ]; then cat $@.tmp > $@; fi
|
@if [ '$(GIT_REVISION)' != '$(OLD_REVISION)' ]; then cp $@.tmp $@; fi
|
||||||
|
@if [ ! -f $@ ]; then cp $@.tmp $@; fi
|
||||||
|
|
||||||
$(autotest_OBJECTS): autotest.c
|
$(autotest_OBJECTS): autotest.c
|
||||||
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@ $<
|
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@ $<
|
||||||
@@ -251,7 +283,7 @@ dist-clean:
|
|||||||
@rm -rf $(all_OBJECTS) *~ core
|
@rm -rf $(all_OBJECTS) *~ core
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -rf $(libuhub_OBJECTS) *~ core $(uhub_BINARY) $(admin_BINARY) $(autotest_BINARY) $(adcrush_BINARY) $(all_OBJECTS) autotest.c && \
|
@rm -rf $(libuhub_OBJECTS) *~ core $(uhub_BINARY) $(admin_BINARY) $(autotest_BINARY) $(adcrush_BINARY) $(all_OBJECTS) autotest.c revision.h revision.h.tmp && \
|
||||||
echo $(MSG_CLEAN)
|
echo $(MSG_CLEAN)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ EXO_TEST(hub_net_startup, {
|
|||||||
|
|
||||||
EXO_TEST(hub_config_initialize, {
|
EXO_TEST(hub_config_initialize, {
|
||||||
config_defaults(&g_config);
|
config_defaults(&g_config);
|
||||||
g_config.server_port = 15111;
|
g_config.server_port = 65111;
|
||||||
return 1;
|
return 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -8,27 +8,27 @@ EXO_TEST(test_message_refc_1, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_2, {
|
EXO_TEST(test_message_refc_2, {
|
||||||
return g_msg->references == 0; // 0
|
return g_msg->references == 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_3, {
|
EXO_TEST(test_message_refc_3, {
|
||||||
adc_msg_incref(g_msg);
|
adc_msg_incref(g_msg);
|
||||||
return g_msg->references == 1; // 1
|
return g_msg->references == 2;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_4, {
|
EXO_TEST(test_message_refc_4, {
|
||||||
adc_msg_incref(g_msg);
|
adc_msg_incref(g_msg);
|
||||||
return g_msg->references == 2; // 2
|
return g_msg->references == 3;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_5, {
|
EXO_TEST(test_message_refc_5, {
|
||||||
adc_msg_free(g_msg);
|
adc_msg_free(g_msg);
|
||||||
return g_msg->references == 1; // 1
|
return g_msg->references == 2;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_6, {
|
EXO_TEST(test_message_refc_6, {
|
||||||
adc_msg_free(g_msg);
|
adc_msg_free(g_msg);
|
||||||
return g_msg->references == 0; // 0
|
return g_msg->references == 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_7, {
|
EXO_TEST(test_message_refc_7, {
|
||||||
|
|||||||
138
autotest/test_sid.tcc
Normal file
138
autotest/test_sid.tcc
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
#include <uhub.h>
|
||||||
|
|
||||||
|
static struct sid_pool* sid_pool = 0;
|
||||||
|
|
||||||
|
struct dummy_user
|
||||||
|
{
|
||||||
|
sid_t sid;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct dummy_user* last = 0;
|
||||||
|
sid_t last_sid = 0;
|
||||||
|
|
||||||
|
EXO_TEST(sid_create_pool, {
|
||||||
|
sid_pool = sid_pool_create(4);
|
||||||
|
return sid_pool != 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_check_0a, {
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 0);
|
||||||
|
return user == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_check_0b, {
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 5);
|
||||||
|
return user == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_alloc_1, {
|
||||||
|
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
|
||||||
|
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
|
||||||
|
last = user;
|
||||||
|
last_sid = user->sid;
|
||||||
|
return (user->sid > 0 && user->sid < 1048576);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_check_1a, {
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
|
||||||
|
return last == user;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_check_1b, {
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid+1);
|
||||||
|
return user == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_alloc_2, {
|
||||||
|
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
|
||||||
|
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
|
||||||
|
last_sid = user->sid;
|
||||||
|
return (user->sid > 0 && user->sid < 1048576);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_check_2, {
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
|
||||||
|
return last != user;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_alloc_3, {
|
||||||
|
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
|
||||||
|
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
|
||||||
|
last_sid = user->sid;
|
||||||
|
return (user->sid > 0 && user->sid < 1048576);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_check_3, {
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
|
||||||
|
return last != user;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_alloc_4, {
|
||||||
|
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
|
||||||
|
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
|
||||||
|
last_sid = user->sid;
|
||||||
|
return (user->sid > 0 && user->sid < 1048576);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_check_4, {
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
|
||||||
|
return last != user;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_alloc_5, {
|
||||||
|
struct dummy_user user;
|
||||||
|
sid_t sid;
|
||||||
|
sid = sid_alloc(sid_pool, (struct hub_user*) &user);
|
||||||
|
return sid == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_check_6, {
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 0);
|
||||||
|
return user == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
EXO_TEST(sid_list_all_1, {
|
||||||
|
sid_t s;
|
||||||
|
size_t n = 0;
|
||||||
|
int ok = 1;
|
||||||
|
for (s = last->sid; s <= last_sid; s++)
|
||||||
|
{
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, s);
|
||||||
|
if (s != (user ? user->sid : -1))
|
||||||
|
{
|
||||||
|
ok = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
return ok && n == 4;
|
||||||
|
});
|
||||||
|
|
||||||
|
#define FREE_SID(N) \
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, N); \
|
||||||
|
sid_free(sid_pool, N); \
|
||||||
|
hub_free(user); \
|
||||||
|
return sid_lookup(sid_pool, N) == NULL;
|
||||||
|
|
||||||
|
EXO_TEST(sid_remove_1, {
|
||||||
|
FREE_SID(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_remove_2, {
|
||||||
|
FREE_SID(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_remove_3, {
|
||||||
|
FREE_SID(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_remove_4, {
|
||||||
|
FREE_SID(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_destroy_pool, {
|
||||||
|
sid_pool_destroy(sid_pool);
|
||||||
|
sid_pool = 0;
|
||||||
|
return sid_pool == 0;
|
||||||
|
});
|
||||||
119
autotest/test_timer.tcc
Normal file
119
autotest/test_timer.tcc
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
#include <uhub.h>
|
||||||
|
|
||||||
|
#define MAX_EVENTS 15
|
||||||
|
static struct timeout_queue* g_queue;
|
||||||
|
static time_t g_now;
|
||||||
|
static size_t g_max;
|
||||||
|
static struct timeout_evt g_events[MAX_EVENTS];
|
||||||
|
|
||||||
|
static size_t g_triggered;
|
||||||
|
|
||||||
|
static void timeout_cb(struct timeout_evt* t)
|
||||||
|
{
|
||||||
|
g_triggered++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
typedef void (*timeout_evt_cb)(struct timeout_evt*);
|
||||||
|
|
||||||
|
struct timeout_evt
|
||||||
|
{
|
||||||
|
time_t timestamp;
|
||||||
|
timeout_evt_cb callback;
|
||||||
|
void* ptr;
|
||||||
|
struct timeout_evt* prev;
|
||||||
|
struct timeout_evt* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
void timeout_evt_initialize(struct timeout_evt*, timeout_evt_cb, void* ptr);
|
||||||
|
void timeout_evt_reset(struct timeout_evt*);
|
||||||
|
int timeout_evt_is_scheduled(struct timeout_evt*);
|
||||||
|
|
||||||
|
|
||||||
|
struct timeout_queue
|
||||||
|
{
|
||||||
|
time_t last;
|
||||||
|
size_t max;
|
||||||
|
struct timeout_evt** events;
|
||||||
|
};
|
||||||
|
|
||||||
|
void timeout_queue_initialize(struct timeout_queue*, time_t now, size_t max);
|
||||||
|
void timeout_queue_shutdown(struct timeout_queue*);
|
||||||
|
size_t timeout_queue_process(struct timeout_queue*, time_t now);
|
||||||
|
void timeout_queue_insert(struct timeout_queue*, struct timeout_evt*, size_t seconds);
|
||||||
|
void timeout_queue_remove(struct timeout_queue*, struct timeout_evt*);
|
||||||
|
void timeout_queue_reschedule(struct timeout_queue*, struct timeout_evt*, size_t seconds);
|
||||||
|
|
||||||
|
size_t timeout_queue_get_next_timeout(struct timeout_queue*, time_t now);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
EXO_TEST(timer_setup,{
|
||||||
|
size_t n;
|
||||||
|
g_queue = hub_malloc_zero(sizeof(struct timeout_queue));
|
||||||
|
g_now = 0;
|
||||||
|
g_max = 5;
|
||||||
|
g_triggered = 0;
|
||||||
|
timeout_queue_initialize(g_queue, g_now, g_max);
|
||||||
|
|
||||||
|
memset(g_events, 0, sizeof(g_events));
|
||||||
|
for (n = 0; n < MAX_EVENTS; n++)
|
||||||
|
{
|
||||||
|
timeout_evt_initialize(&g_events[n], timeout_cb, &g_events[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_queue != NULL;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
EXO_TEST(timer_check_timeout_0,{
|
||||||
|
return timeout_queue_get_next_timeout(g_queue, g_now) == g_max;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
EXO_TEST(timer_add_event_1,{
|
||||||
|
timeout_queue_insert(g_queue, &g_events[0], 2);
|
||||||
|
return g_events[0].prev != NULL;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(timer_check_timeout_1,{
|
||||||
|
return timeout_queue_get_next_timeout(g_queue, g_now) == 2;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(timer_remove_event_1,{
|
||||||
|
timeout_queue_remove(g_queue, &g_events[0]);
|
||||||
|
return g_events[0].prev == NULL;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(timer_check_timeout_2,{
|
||||||
|
return timeout_queue_get_next_timeout(g_queue, g_now) == g_max;
|
||||||
|
});
|
||||||
|
|
||||||
|
/* test re-removing an event - should not crash! */
|
||||||
|
EXO_TEST(timer_remove_event_1_no_crash,{
|
||||||
|
timeout_queue_remove(g_queue, &g_events[0]);
|
||||||
|
return g_events[0].prev == NULL;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(timer_add_5_events_1,{
|
||||||
|
timeout_queue_insert(g_queue, &g_events[0], 0);
|
||||||
|
timeout_queue_insert(g_queue, &g_events[1], 1);
|
||||||
|
timeout_queue_insert(g_queue, &g_events[2], 2);
|
||||||
|
timeout_queue_insert(g_queue, &g_events[3], 3);
|
||||||
|
timeout_queue_insert(g_queue, &g_events[4], 4);
|
||||||
|
|
||||||
|
return (g_events[0].prev != NULL &&
|
||||||
|
g_events[1].prev != NULL &&
|
||||||
|
g_events[2].prev != NULL &&
|
||||||
|
g_events[3].prev != NULL &&
|
||||||
|
g_events[4].prev != NULL);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(timer_check_5_events_1,{
|
||||||
|
return timeout_queue_get_next_timeout(g_queue, g_now) == 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(timer_process_5_events_1,{
|
||||||
|
g_now = 4;
|
||||||
|
return timeout_queue_process(g_queue, g_now) == g_triggered;
|
||||||
|
});
|
||||||
6
debian/changelog
vendored
6
debian/changelog
vendored
@@ -1,3 +1,9 @@
|
|||||||
|
uhub (0.3.1-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* Updated version number.
|
||||||
|
|
||||||
|
-- Jan Vidar Krey <janvidar@extatic.org> Mon 04 Apr 2010 16:44:21 +0200
|
||||||
|
|
||||||
uhub (0.3.0-2) unstable; urgency=low
|
uhub (0.3.0-2) unstable; urgency=low
|
||||||
|
|
||||||
* Fixed init.d scripts.
|
* Fixed init.d scripts.
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ file_motd=/etc/uhub/motd.txt
|
|||||||
file_rules=/etc/uhub/rules.txt
|
file_rules=/etc/uhub/rules.txt
|
||||||
|
|
||||||
|
|
||||||
# Slots\share\hubs limits
|
# Slots/share/hubs limits
|
||||||
limit_max_hubs_user = 0
|
limit_max_hubs_user = 0
|
||||||
limit_max_hubs_reg = 0
|
limit_max_hubs_reg = 0
|
||||||
limit_max_hubs_op = 0
|
limit_max_hubs_op = 0
|
||||||
@@ -66,6 +66,18 @@ limit_max_share = 0
|
|||||||
limit_min_slots = 0
|
limit_min_slots = 0
|
||||||
limit_max_slots = 0
|
limit_max_slots = 0
|
||||||
|
|
||||||
|
# Flood control support:
|
||||||
|
# set the interval to 5 seconds
|
||||||
|
flood_ctl_interval = 5
|
||||||
|
|
||||||
|
# Then the maximum chat, connect, search, updates etc will be measured over 5 seconds.
|
||||||
|
# So, 3 chat messages per 5 seconds allowed.
|
||||||
|
flood_ctl_chat=3
|
||||||
|
flood_ctl_connect=20
|
||||||
|
flood_ctl_search=1
|
||||||
|
flood_ctl_update=2
|
||||||
|
flood_ctl_extras=5
|
||||||
|
|
||||||
# chat control
|
# chat control
|
||||||
# if chat_is_privileged=yes only registered users may write in main chat
|
# if chat_is_privileged=yes only registered users may write in main chat
|
||||||
chat_is_privileged = no
|
chat_is_privileged = no
|
||||||
@@ -74,6 +86,11 @@ chat_is_privileged = no
|
|||||||
# non-operator users.
|
# non-operator users.
|
||||||
chat_only = no
|
chat_only = no
|
||||||
|
|
||||||
|
# if obsolete_clients=1 allows old clients to enter , 0 gives an error message (msg_proto_obsolete_adc0) if they try connect
|
||||||
|
# defaults obsolete_clients=1
|
||||||
|
obsolete_clients=1
|
||||||
|
|
||||||
|
|
||||||
# Configure status message as sent to clients in different circumstances.
|
# Configure status message as sent to clients in different circumstances.
|
||||||
msg_hub_full = Hub is full
|
msg_hub_full = Hub is full
|
||||||
msg_hub_disabled = Hub is disabled
|
msg_hub_disabled = Hub is disabled
|
||||||
@@ -104,5 +121,16 @@ msg_user_slots_high = User have too many upload slots
|
|||||||
msg_user_hub_limit_low = User is on too few hubs
|
msg_user_hub_limit_low = User is on too few hubs
|
||||||
msg_user_hub_limit_high = User is on too many hubs
|
msg_user_hub_limit_high = User is on too many hubs
|
||||||
msg_error_no_memory = No memory
|
msg_error_no_memory = No memory
|
||||||
|
msg_user_flood_chat = Chat flood detected, messages are dropped.
|
||||||
|
msg_user_flood_connect = Connect flood detected, connection refused.
|
||||||
|
msg_user_flood_search = Search flood detected, search is stopped.
|
||||||
|
msg_user_flood_update = Update flood detected.
|
||||||
|
msg_user_flood_extras = Flood detected.
|
||||||
|
|
||||||
|
# If a client that supports ADC but not a compatible hash algorithm (tiger),
|
||||||
|
# then the hub cannot accept the client:
|
||||||
|
msg_proto_no_common_hash = No common hash algorithm.
|
||||||
|
|
||||||
|
# Message to be shown to old clients using an older version of ADC than ADC/1.0
|
||||||
|
msg_proto_obsolete_adc0 = Client is using an obsolete ADC protocol version.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
Summary: High performance ADC p2p hub.
|
Summary: High performance ADC p2p hub.
|
||||||
Name: uhub
|
Name: uhub
|
||||||
Version: 0.3.0
|
Version: 0.3.1
|
||||||
Release: 3
|
Release: 3
|
||||||
License: GPLv3
|
License: GPLv3
|
||||||
Group: Networking/File transfer
|
Group: Networking/File transfer
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -26,7 +26,9 @@
|
|||||||
uhub_assert(X->capacity); \
|
uhub_assert(X->capacity); \
|
||||||
uhub_assert(X->length); \
|
uhub_assert(X->length); \
|
||||||
uhub_assert(X->length <= X->capacity); \
|
uhub_assert(X->length <= X->capacity); \
|
||||||
|
uhub_assert(X->references > 0); \
|
||||||
uhub_assert(X->length == strlen(X->cache));
|
uhub_assert(X->length == strlen(X->cache));
|
||||||
|
#define ADC_MSG_NULL_ON_FREE
|
||||||
#else
|
#else
|
||||||
#define ADC_MSG_ASSERT(X) do { } while(0)
|
#define ADC_MSG_ASSERT(X) do { } while(0)
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
@@ -53,40 +55,18 @@ static void* msg_malloc_zero(size_t size)
|
|||||||
static void msg_free(void* ptr)
|
static void msg_free(void* ptr)
|
||||||
{
|
{
|
||||||
LOG_MEMORY("msg_free: %p", ptr);
|
LOG_MEMORY("msg_free: %p", ptr);
|
||||||
// hub_free(ptr);
|
hub_free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <sys/mman.h>
|
|
||||||
static void adc_msg_protect(struct adc_message* cmd)
|
|
||||||
{
|
|
||||||
LOG_MEMORY("msg_prot: %p %d", cmd, cmd->capacity);
|
|
||||||
mprotect(cmd, sizeof(cmd), PROT_READ);
|
|
||||||
mprotect(cmd->cache, sizeof(cmd->capacity), PROT_READ);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void adc_msg_unprotect(struct adc_message* cmd)
|
|
||||||
{
|
|
||||||
LOG_MEMORY("msg_unprot: %p %d", cmd, cmd->capacity);
|
|
||||||
mprotect(cmd, sizeof(cmd), PROT_READ | PROT_WRITE);
|
|
||||||
mprotect(cmd->cache, sizeof(cmd->capacity), PROT_READ | PROT_WRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define msg_malloc(X) hub_malloc(X)
|
#define msg_malloc(X) hub_malloc(X)
|
||||||
#define msg_malloc_zero(X) hub_malloc_zero(X)
|
#define msg_malloc_zero(X) hub_malloc_zero(X)
|
||||||
#define msg_free(X) hub_free(X)
|
#define msg_free(X) hub_free(X)
|
||||||
|
|
||||||
#endif /* MSG_MEMORY_DEBUG */
|
#endif /* MSG_MEMORY_DEBUG */
|
||||||
|
|
||||||
|
|
||||||
struct adc_message* adc_msg_incref(struct adc_message* msg)
|
struct adc_message* adc_msg_incref(struct adc_message* msg)
|
||||||
{
|
{
|
||||||
if (!msg) return 0;
|
|
||||||
#ifndef ADC_MESSAGE_INCREF
|
#ifndef ADC_MESSAGE_INCREF
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_unprotect(msg);
|
|
||||||
#endif
|
|
||||||
msg->references++;
|
msg->references++;
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
#ifdef MSG_MEMORY_DEBUG
|
||||||
adc_msg_protect(msg);
|
adc_msg_protect(msg);
|
||||||
@@ -108,6 +88,9 @@ static int adc_msg_grow(struct adc_message* msg, size_t size)
|
|||||||
char* buf;
|
char* buf;
|
||||||
size_t newsize = 0;
|
size_t newsize = 0;
|
||||||
|
|
||||||
|
if (!msg)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (msg->capacity > size)
|
if (msg->capacity > size)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -204,20 +187,15 @@ void adc_msg_free(struct adc_message* msg)
|
|||||||
|
|
||||||
ADC_MSG_ASSERT(msg);
|
ADC_MSG_ASSERT(msg);
|
||||||
|
|
||||||
if (msg->references > 0)
|
|
||||||
{
|
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_unprotect(msg);
|
|
||||||
#endif
|
|
||||||
msg->references--;
|
msg->references--;
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_protect(msg);
|
if (msg->references == 0)
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
#ifdef ADC_MSG_NULL_ON_FREE
|
||||||
adc_msg_unprotect(msg);
|
if (msg->cache)
|
||||||
|
{
|
||||||
|
*msg->cache = 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
msg_free(msg->cache);
|
msg_free(msg->cache);
|
||||||
|
|
||||||
@@ -256,20 +234,24 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
|||||||
copy->length = cmd->length;
|
copy->length = cmd->length;
|
||||||
copy->capacity = 0;
|
copy->capacity = 0;
|
||||||
copy->priority = cmd->priority;
|
copy->priority = cmd->priority;
|
||||||
copy->references = 0;
|
copy->references = 1;
|
||||||
copy->feature_cast_include = 0;
|
copy->feature_cast_include = 0;
|
||||||
copy->feature_cast_exclude = 0;
|
copy->feature_cast_exclude = 0;
|
||||||
|
|
||||||
if (cmd->cache)
|
|
||||||
{
|
|
||||||
if (!adc_msg_grow(copy, copy->length))
|
if (!adc_msg_grow(copy, copy->length))
|
||||||
{
|
{
|
||||||
adc_msg_free(copy);
|
adc_msg_free(copy);
|
||||||
return NULL; /* OOM */
|
return NULL; /* OOM */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!copy->cache)
|
||||||
|
{
|
||||||
|
adc_msg_free(copy);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(copy->cache, cmd->cache, cmd->length);
|
memcpy(copy->cache, cmd->cache, cmd->length);
|
||||||
copy->cache[copy->length] = 0;
|
copy->cache[copy->length] = 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd->feature_cast_include)
|
if (cmd->feature_cast_include)
|
||||||
{
|
{
|
||||||
@@ -295,9 +277,6 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
|||||||
|
|
||||||
ADC_MSG_ASSERT(copy);
|
ADC_MSG_ASSERT(copy);
|
||||||
|
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_protect(copy);
|
|
||||||
#endif
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,6 +339,7 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
|
|
||||||
command->cmd = FOURCC(line[0], line[1], line[2], line[3]);
|
command->cmd = FOURCC(line[0], line[1], line[2], line[3]);
|
||||||
command->priority = 0;
|
command->priority = 0;
|
||||||
|
command->references = 1;
|
||||||
|
|
||||||
switch (prefix)
|
switch (prefix)
|
||||||
{
|
{
|
||||||
@@ -443,7 +423,6 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
|
|
||||||
if (n == 10)
|
if (n == 10)
|
||||||
ok = 0;
|
ok = 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'D':
|
case 'D':
|
||||||
@@ -510,10 +489,6 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ADC_MSG_ASSERT(command);
|
ADC_MSG_ASSERT(command);
|
||||||
|
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_protect(command);
|
|
||||||
#endif
|
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,7 +502,6 @@ struct adc_message* adc_msg_create(const char* line)
|
|||||||
struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
||||||
{
|
{
|
||||||
struct adc_message* msg = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
|
struct adc_message* msg = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
|
||||||
|
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return NULL; /* OOM */
|
return NULL; /* OOM */
|
||||||
|
|
||||||
@@ -554,11 +528,7 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
|||||||
|
|
||||||
msg->cmd = fourcc;
|
msg->cmd = fourcc;
|
||||||
msg->priority = 0;
|
msg->priority = 0;
|
||||||
|
msg->references = 1;
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_protect(msg);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,10 +668,6 @@ void adc_msg_terminate(struct adc_message* cmd)
|
|||||||
adc_msg_cache_append(cmd, "\n", 1);
|
adc_msg_cache_append(cmd, "\n", 1);
|
||||||
}
|
}
|
||||||
ADC_MSG_ASSERT(cmd);
|
ADC_MSG_ASSERT(cmd);
|
||||||
|
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_protect(cmd);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: this looks bogus */
|
/* FIXME: this looks bogus */
|
||||||
@@ -709,10 +675,6 @@ void adc_msg_unterminate(struct adc_message* cmd)
|
|||||||
{
|
{
|
||||||
ADC_MSG_ASSERT(cmd);
|
ADC_MSG_ASSERT(cmd);
|
||||||
|
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_unprotect(cmd);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (cmd->length > 0 && cmd->cache[cmd->length-1] == '\n')
|
if (cmd->length > 0 && cmd->cache[cmd->length-1] == '\n')
|
||||||
{
|
{
|
||||||
cmd->length--;
|
cmd->length--;
|
||||||
@@ -794,7 +756,7 @@ char* adc_msg_get_argument(struct adc_message* cmd, int offset)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
argument = hub_strdup(&start[1]);
|
argument = hub_strdup(&start[1]);
|
||||||
if (argument && argument[strlen(argument)-1] == '\n')
|
if (argument && *argument && argument[strlen(argument)-1] == '\n')
|
||||||
argument[strlen(argument)-1] = 0;
|
argument[strlen(argument)-1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -884,9 +846,6 @@ int adc_msg_unescape_length(const char* str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char* adc_msg_unescape(const char* string)
|
char* adc_msg_unescape(const char* string)
|
||||||
{
|
{
|
||||||
char* new_string = msg_malloc(adc_msg_unescape_length(string)+1);
|
char* new_string = msg_malloc(adc_msg_unescape_length(string)+1);
|
||||||
@@ -905,14 +864,12 @@ char* adc_msg_unescape(const char* string)
|
|||||||
*ptr++ = '\n';
|
*ptr++ = '\n';
|
||||||
else
|
else
|
||||||
*ptr++ = *str;
|
*ptr++ = *str;
|
||||||
|
|
||||||
escaped = 0;
|
escaped = 0;
|
||||||
} else {
|
} else {
|
||||||
if (*str == '\\')
|
if (*str == '\\')
|
||||||
escaped = 1;
|
escaped = 1;
|
||||||
else
|
else
|
||||||
*ptr++ = *str;
|
*ptr++ = *str;
|
||||||
|
|
||||||
}
|
}
|
||||||
str++;
|
str++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -119,6 +119,14 @@ void sid_pool_destroy(struct sid_pool* pool)
|
|||||||
|
|
||||||
sid_t sid_alloc(struct sid_pool* pool, struct hub_user* user)
|
sid_t sid_alloc(struct sid_pool* pool, struct hub_user* user)
|
||||||
{
|
{
|
||||||
|
if (pool->count >= (pool->max - pool->min))
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_SID
|
||||||
|
LOG_DUMP("SID_POOL: alloc, sid pool is full.");
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
sid_t n = (++pool->count);
|
sid_t n = (++pool->count);
|
||||||
for (; (pool->map[n % pool->max]); n++) ;
|
for (; (pool->map[n % pool->max]); n++) ;
|
||||||
|
|
||||||
@@ -140,7 +148,7 @@ void sid_free(struct sid_pool* pool, sid_t sid)
|
|||||||
|
|
||||||
struct hub_user* sid_lookup(struct sid_pool* pool, sid_t sid)
|
struct hub_user* sid_lookup(struct sid_pool* pool, sid_t sid)
|
||||||
{
|
{
|
||||||
if (!sid || (sid > pool->max))
|
if (!sid || (sid >= pool->max))
|
||||||
return 0;
|
return 0;
|
||||||
return pool->map[sid];
|
return pool->map[sid];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -176,14 +176,10 @@ static int check_cmd_addr(const char* cmd, struct linked_list* list, char* line,
|
|||||||
|
|
||||||
static int acl_parse_line(char* line, int line_count, void* ptr_data)
|
static int acl_parse_line(char* line, int line_count, void* ptr_data)
|
||||||
{
|
{
|
||||||
char* pos;
|
|
||||||
struct acl_handle* handle = (struct acl_handle*) ptr_data;
|
struct acl_handle* handle = (struct acl_handle*) ptr_data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if ((pos = strchr(line, '#')) != NULL)
|
strip_off_ini_line_comments(line, line_count);
|
||||||
{
|
|
||||||
pos[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
line = strip_white_space(line);
|
line = strip_white_space(line);
|
||||||
if (!*line)
|
if (!*line)
|
||||||
@@ -358,20 +354,10 @@ int acl_is_user_denied(struct acl_handle* handle, const char* data)
|
|||||||
|
|
||||||
int acl_user_ban_nick(struct acl_handle* handle, const char* nick)
|
int acl_user_ban_nick(struct acl_handle* handle, const char* nick)
|
||||||
{
|
{
|
||||||
char* data = 0;
|
char* data = hub_strdup(nick);
|
||||||
struct hub_user_access_info* info = hub_malloc_zero(sizeof(struct hub_user_access_info));
|
|
||||||
|
|
||||||
if (!info)
|
|
||||||
{
|
|
||||||
LOG_ERROR("ACL error: Out of memory!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = hub_strdup(nick);
|
|
||||||
if (!data)
|
if (!data)
|
||||||
{
|
{
|
||||||
LOG_ERROR("ACL error: Out of memory!");
|
LOG_ERROR("ACL error: Out of memory!");
|
||||||
hub_free(info);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,19 +367,10 @@ int acl_user_ban_nick(struct acl_handle* handle, const char* nick)
|
|||||||
|
|
||||||
int acl_user_ban_cid(struct acl_handle* handle, const char* cid)
|
int acl_user_ban_cid(struct acl_handle* handle, const char* cid)
|
||||||
{
|
{
|
||||||
char* data;
|
char* data = hub_strdup(cid);
|
||||||
struct hub_user_access_info* info = hub_malloc_zero(sizeof(struct hub_user_access_info));
|
|
||||||
if (!info)
|
|
||||||
{
|
|
||||||
LOG_ERROR("ACL error: Out of memory!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = hub_strdup(cid);
|
|
||||||
if (!data)
|
if (!data)
|
||||||
{
|
{
|
||||||
LOG_ERROR("ACL error: Out of memory!");
|
LOG_ERROR("ACL error: Out of memory!");
|
||||||
hub_free(info);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ static int command_getip(struct hub_info* hub, struct hub_user* user, struct hub
|
|||||||
char* nick = list_get_first(cmd->args);
|
char* nick = list_get_first(cmd->args);
|
||||||
struct hub_user* target;
|
struct hub_user* target;
|
||||||
|
|
||||||
if (!nick);
|
if (!nick)
|
||||||
return -1; // FIXME: bad syntax/OOM
|
return -1; // FIXME: bad syntax/OOM
|
||||||
|
|
||||||
target = uman_get_user_by_nick(hub, nick);
|
target = uman_get_user_by_nick(hub, nick);
|
||||||
@@ -347,7 +347,7 @@ static int command_getip(struct hub_info* hub, struct hub_user* user, struct hub
|
|||||||
if (!target)
|
if (!target)
|
||||||
return command_status_user_not_found(hub, user, cmd, nick);
|
return command_status_user_not_found(hub, user, cmd, nick);
|
||||||
|
|
||||||
snprintf(tmp, 128, "%s has address \"%s\"", nick, user_get_address(user));
|
snprintf(tmp, 128, "%s has address \"%s\"", nick, user_get_address(target));
|
||||||
return command_status(hub, user, cmd, tmp);
|
return command_status(hub, user, cmd, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,11 +412,48 @@ static int command_whoip(struct hub_info* hub, struct hub_user* user, struct hub
|
|||||||
|
|
||||||
static int command_broadcast(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
static int command_broadcast(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
{
|
{
|
||||||
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen((cmd->message + 12)) + 6);
|
size_t offset = 12;
|
||||||
adc_msg_add_argument(command, (cmd->message + 12));
|
#if USE_OLD_BROADCAST_STYLE
|
||||||
|
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen((cmd->message + offset)) + 6);
|
||||||
|
adc_msg_add_argument(command, (cmd->message + offset));
|
||||||
route_to_all(hub, command);
|
route_to_all(hub, command);
|
||||||
adc_msg_free(command);
|
adc_msg_free(command);
|
||||||
return 0;
|
return 0;
|
||||||
|
#else
|
||||||
|
size_t message_len = strlen(cmd->message + offset);
|
||||||
|
struct adc_message* command = 0;
|
||||||
|
char pm_flag[7] = "PM";
|
||||||
|
char from_sid[5];
|
||||||
|
char buffer[128];
|
||||||
|
size_t recipients = 0;
|
||||||
|
|
||||||
|
memcpy(from_sid, sid_to_string(user->id.sid), sizeof(from_sid));
|
||||||
|
memcpy(pm_flag + 2, from_sid, sizeof(from_sid));
|
||||||
|
|
||||||
|
struct hub_user* target = (struct hub_user*) list_get_first(hub->users->list);
|
||||||
|
while (target)
|
||||||
|
{
|
||||||
|
if (target != user)
|
||||||
|
{
|
||||||
|
recipients++;
|
||||||
|
command = adc_msg_construct(ADC_CMD_DMSG, message_len + 23);
|
||||||
|
if (!command)
|
||||||
|
break;
|
||||||
|
|
||||||
|
adc_msg_add_argument(command, from_sid);
|
||||||
|
adc_msg_add_argument(command, sid_to_string(target->id.sid));
|
||||||
|
adc_msg_add_argument(command, (cmd->message + offset));
|
||||||
|
adc_msg_add_argument(command, pm_flag);
|
||||||
|
|
||||||
|
route_to_user(hub, target, command);
|
||||||
|
adc_msg_free(command);
|
||||||
|
}
|
||||||
|
target = (struct hub_user*) list_get_next(hub->users->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(buffer, sizeof(buffer), "*** %s: Delivered to " PRINTF_SIZE_T " user%s", cmd->prefix, recipients, (recipients != 1 ? "s" : ""));
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int command_history(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
static int command_history(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
|
|||||||
@@ -29,459 +29,54 @@
|
|||||||
#define INT_MIN (-0x7fffffff - 1)
|
#define INT_MIN (-0x7fffffff - 1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CFG_APPLY_BOOLEAN(KEY, TARGET) \
|
static int apply_boolean(const char* key, const char* data, int* target)
|
||||||
if (strcmp(KEY, key) == 0) \
|
|
||||||
{ \
|
|
||||||
if (strlen(data) == 1 && (data[0] == '1')) TARGET = 1; \
|
|
||||||
else if (strlen(data) == 1 && (data[0] == '0')) TARGET = 0; \
|
|
||||||
else if (strncasecmp(data, "true", 4) == 0) TARGET = 1; \
|
|
||||||
else if (strncasecmp(data, "false", 5) == 0) TARGET = 0; \
|
|
||||||
else if (strncasecmp(data, "yes", 3) == 0) TARGET = 1; \
|
|
||||||
else if (strncasecmp(data, "no", 2) == 0) TARGET = 0; \
|
|
||||||
else if (strncasecmp(data, "on", 2) == 0) TARGET = 1; \
|
|
||||||
else if (strncasecmp(data, "off", 3) == 0) TARGET = 0; \
|
|
||||||
else\
|
|
||||||
{ \
|
|
||||||
LOG_FATAL("Configuration error on line %d: '%s' must be either '1' or '0'", line_count, key); \
|
|
||||||
return -1; \
|
|
||||||
} \
|
|
||||||
TARGET |= 0x80000000; \
|
|
||||||
return 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CFG_APPLY_STRING(KEY, TARGET) \
|
|
||||||
if (strcmp(KEY, key) == 0) \
|
|
||||||
{ \
|
|
||||||
TARGET = hub_strdup(data); \
|
|
||||||
return 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define CFG_APPLY_INTEGER(KEY, TARGET) \
|
|
||||||
if (strcmp(KEY, key) == 0) \
|
|
||||||
{ \
|
|
||||||
char* endptr; \
|
|
||||||
int val; \
|
|
||||||
errno = 0; \
|
|
||||||
val = strtol(data, &endptr, 10); \
|
|
||||||
if (((errno == ERANGE && (val == INT_MAX || val == INT_MIN)) || (errno != 0 && val == 0)) || endptr == data) { \
|
|
||||||
LOG_FATAL("Configuration error on line %d: '%s' must be a number", line_count, key); \
|
|
||||||
return -1; \
|
|
||||||
} \
|
|
||||||
TARGET = val; \
|
|
||||||
return 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define DEFAULT_STRING(KEY, VALUE) \
|
|
||||||
{ \
|
|
||||||
if (config->KEY == 0) \
|
|
||||||
config->KEY = hub_strdup(VALUE); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEFAULT_INTEGER(KEY, VALUE) \
|
|
||||||
{ \
|
|
||||||
if (config->KEY == 0) \
|
|
||||||
config->KEY = VALUE; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEFAULT_BOOLEAN(KEY, VALUE) \
|
|
||||||
{ \
|
|
||||||
if (config->KEY & 0x80000000) \
|
|
||||||
{ \
|
|
||||||
config->KEY = config->KEY & 0x000000ff; \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
config->KEY = VALUE; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GET_STR(NAME) CFG_APPLY_STRING ( #NAME , config->NAME )
|
|
||||||
#define GET_INT(NAME) CFG_APPLY_INTEGER( #NAME , config->NAME )
|
|
||||||
#define GET_BOOL(NAME) CFG_APPLY_BOOLEAN( #NAME , config->NAME )
|
|
||||||
#define IGNORED(NAME) \
|
|
||||||
if (strcmp(#NAME, key) == 0) \
|
|
||||||
{ \
|
|
||||||
LOG_WARN("Configuration option %s deprecated and ingnored.", key); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
|
|
||||||
/* default configuration values */
|
|
||||||
#define DEF_SERVER_BIND_ADDR "any"
|
|
||||||
#define DEF_SERVER_PORT 1511
|
|
||||||
#define DEF_SERVER_BACKLOG 50
|
|
||||||
#define DEF_SERVER_ALT_PORTS ""
|
|
||||||
#define DEF_HUB_NAME "uhub"
|
|
||||||
#define DEF_HUB_DESCRIPTION ""
|
|
||||||
#define DEF_HUB_ENABLED 1
|
|
||||||
#define DEF_FILE_ACL ""
|
|
||||||
#define DEF_FILE_MOTD ""
|
|
||||||
#define DEF_FILE_RULES ""
|
|
||||||
#define DEF_MAX_USERS 500
|
|
||||||
#define DEF_MAX_CHAT_HISTORY 20
|
|
||||||
#define DEF_MAX_LOGOUT_LOG 100
|
|
||||||
#define DEF_MAX_RECV_BUFFER 4096
|
|
||||||
#define DEF_MAX_SEND_BUFFER 131072
|
|
||||||
#define DEF_MAX_SEND_BUFFER_SOFT 98304
|
|
||||||
#define DEF_SHOW_BANNER 1
|
|
||||||
#define DEF_SHOW_BANNER_SYS_INFO 1
|
|
||||||
#define DEF_REGISTERED_USERS_ONLY 0
|
|
||||||
#define DEF_CHAT_ONLY 0
|
|
||||||
#define DEF_CHAT_IS_PRIVILEGED 0
|
|
||||||
#define DEF_LOW_BANDWIDTH_MODE 0
|
|
||||||
#define DEF_LIMIT_MAX_HUBS_USER 0
|
|
||||||
#define DEF_LIMIT_MAX_HUBS_REG 0
|
|
||||||
#define DEF_LIMIT_MAX_HUBS_OP 0
|
|
||||||
#define DEF_LIMIT_MAX_HUBS 0
|
|
||||||
#define DEF_LIMIT_MIN_HUBS_USER 0
|
|
||||||
#define DEF_LIMIT_MIN_HUBS_REG 0
|
|
||||||
#define DEF_LIMIT_MIN_HUBS_OP 0
|
|
||||||
#define DEF_LIMIT_MIN_SHARE 0
|
|
||||||
#define DEF_LIMIT_MAX_SHARE 0
|
|
||||||
#define DEF_LIMIT_MIN_SLOTS 0
|
|
||||||
#define DEF_LIMIT_MAX_SLOTS 0
|
|
||||||
#define DEF_TLS_ENABLE 0
|
|
||||||
#define DEF_TLS_REQUIRE 1
|
|
||||||
#define DEF_TLS_PRIVATE_KEY ""
|
|
||||||
#define DEF_TLS_CERTIFICATE ""
|
|
||||||
#define DEF_MSG_HUB_FULL "Hub is full"
|
|
||||||
#define DEF_MSG_HUB_DISABLED "Hub is disabled"
|
|
||||||
#define DEF_MSG_HUB_REGISTERED_USERS_ONLY "Hub is for registered users only"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_MISSING "No nickname given"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_MULTIPLE "Multiple nicknames given"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_INVALID "Nickname is invalid"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_LONG "Nickname too long"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_SHORT "Nickname too short"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_SPACES "Nickname cannot start with spaces"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_BAD_CHARS "Nickname contains invalid characters"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_NOT_UTF8 "Nickname is not valid utf8"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_TAKEN "Nickname is already in use"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_RESTRICTED "Nickname cannot be used on this hub"
|
|
||||||
#define DEF_MSG_INF_ERROR_CID_INVALID "CID is not valid"
|
|
||||||
#define DEF_MSG_INF_ERROR_CID_MISSING "CID is not specified"
|
|
||||||
#define DEF_MSG_INF_ERROR_CID_TAKEN "CID is taken"
|
|
||||||
#define DEF_MSG_INF_ERROR_PID_MISSING "PID is not specified"
|
|
||||||
#define DEF_MSG_INF_ERROR_PID_INVALID "PID is invalid"
|
|
||||||
#define DEF_MSG_BAN_PERMANENTLY "Banned permanently"
|
|
||||||
#define DEF_MSG_BAN_TEMPORARILY "Banned temporarily"
|
|
||||||
#define DEF_MSG_AUTH_INVALID_PASSWORD "Password is wrong"
|
|
||||||
#define DEF_MSG_AUTH_USER_NOT_FOUND "User not found in password database"
|
|
||||||
#define DEF_MSG_ERROR_NO_MEMORY "No memory"
|
|
||||||
#define DEF_MSG_USER_SHARE_SIZE_LOW "User is not sharing enough"
|
|
||||||
#define DEF_MSG_USER_SHARE_SIZE_HIGH "User is sharing too much"
|
|
||||||
#define DEF_MSG_USER_SLOTS_LOW "User have too few upload slots."
|
|
||||||
#define DEF_MSG_USER_SLOTS_HIGH "User have too many upload slots."
|
|
||||||
#define DEF_MSG_USER_HUB_LIMIT_LOW "User is on too few hubs."
|
|
||||||
#define DEF_MSG_USER_HUB_LIMIT_HIGH "User is on too many hubs."
|
|
||||||
|
|
||||||
void config_defaults(struct hub_config* config)
|
|
||||||
{
|
{
|
||||||
DEFAULT_STRING (server_bind_addr, DEF_SERVER_BIND_ADDR);
|
if (strlen(data) == 1 && (data[0] == '1')) *target = 1;
|
||||||
DEFAULT_STRING (hub_name, DEF_HUB_NAME);
|
else if (strlen(data) == 1 && (data[0] == '0')) *target = 0;
|
||||||
DEFAULT_STRING (hub_description, DEF_HUB_DESCRIPTION);
|
else if (strncasecmp(data, "true", 4) == 0) *target = 1;
|
||||||
DEFAULT_BOOLEAN(hub_enabled, DEF_HUB_ENABLED);
|
else if (strncasecmp(data, "false", 5) == 0) *target = 0;
|
||||||
DEFAULT_STRING (file_acl, DEF_FILE_ACL);
|
else if (strncasecmp(data, "yes", 3) == 0) *target = 1;
|
||||||
DEFAULT_STRING (file_motd, DEF_FILE_MOTD);
|
else if (strncasecmp(data, "no", 2) == 0) *target = 0;
|
||||||
DEFAULT_STRING (file_rules, DEF_FILE_RULES);
|
else if (strncasecmp(data, "on", 2) == 0) *target = 1;
|
||||||
DEFAULT_INTEGER(server_port, DEF_SERVER_PORT);
|
else if (strncasecmp(data, "off", 3) == 0) *target = 0;
|
||||||
DEFAULT_INTEGER(server_listen_backlog, DEF_SERVER_BACKLOG);
|
else
|
||||||
DEFAULT_STRING (server_alt_ports, DEF_SERVER_ALT_PORTS);
|
return 0;
|
||||||
DEFAULT_INTEGER(max_users, DEF_MAX_USERS);
|
return 1;
|
||||||
DEFAULT_INTEGER(max_chat_history, DEF_MAX_CHAT_HISTORY);
|
|
||||||
DEFAULT_INTEGER(max_logout_log, DEF_MAX_LOGOUT_LOG);
|
|
||||||
DEFAULT_INTEGER(max_recv_buffer, DEF_MAX_RECV_BUFFER);
|
|
||||||
DEFAULT_INTEGER(max_send_buffer, DEF_MAX_SEND_BUFFER);
|
|
||||||
DEFAULT_INTEGER(max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
|
|
||||||
DEFAULT_BOOLEAN(show_banner, DEF_SHOW_BANNER);
|
|
||||||
DEFAULT_BOOLEAN(show_banner_sys_info, DEF_SHOW_BANNER_SYS_INFO);
|
|
||||||
DEFAULT_BOOLEAN(chat_only, DEF_CHAT_ONLY);
|
|
||||||
DEFAULT_BOOLEAN(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
|
|
||||||
DEFAULT_BOOLEAN(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
|
|
||||||
DEFAULT_BOOLEAN(registered_users_only, DEF_REGISTERED_USERS_ONLY);
|
|
||||||
|
|
||||||
/* Limits enforced on users */
|
|
||||||
DEFAULT_INTEGER(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
|
|
||||||
DEFAULT_INTEGER(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
|
|
||||||
DEFAULT_INTEGER(limit_max_hubs_op, DEF_LIMIT_MAX_HUBS_OP);
|
|
||||||
DEFAULT_INTEGER(limit_min_hubs_user, DEF_LIMIT_MIN_HUBS_USER);
|
|
||||||
DEFAULT_INTEGER(limit_min_hubs_reg, DEF_LIMIT_MIN_HUBS_REG);
|
|
||||||
DEFAULT_INTEGER(limit_min_hubs_op, DEF_LIMIT_MIN_HUBS_OP);
|
|
||||||
DEFAULT_INTEGER(limit_max_hubs, DEF_LIMIT_MAX_HUBS);
|
|
||||||
DEFAULT_INTEGER(limit_min_share, DEF_LIMIT_MIN_SHARE);
|
|
||||||
DEFAULT_INTEGER(limit_max_share, DEF_LIMIT_MAX_SHARE);
|
|
||||||
DEFAULT_INTEGER(limit_min_slots, DEF_LIMIT_MIN_SLOTS);
|
|
||||||
DEFAULT_INTEGER(limit_max_slots, DEF_LIMIT_MAX_SLOTS);
|
|
||||||
|
|
||||||
/* Status/error strings */
|
|
||||||
DEFAULT_STRING (msg_hub_full, DEF_MSG_HUB_FULL);
|
|
||||||
DEFAULT_STRING (msg_hub_disabled, DEF_MSG_HUB_DISABLED)
|
|
||||||
DEFAULT_STRING (msg_hub_registered_users_only, DEF_MSG_HUB_REGISTERED_USERS_ONLY);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_missing, DEF_MSG_INF_ERROR_NICK_MISSING);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_multiple, DEF_MSG_INF_ERROR_NICK_MULTIPLE);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_invalid, DEF_MSG_INF_ERROR_NICK_INVALID);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_long, DEF_MSG_INF_ERROR_NICK_LONG);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_short, DEF_MSG_INF_ERROR_NICK_SHORT);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_spaces, DEF_MSG_INF_ERROR_NICK_SPACES);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_bad_chars, DEF_MSG_INF_ERROR_NICK_BAD_CHARS);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_not_utf8, DEF_MSG_INF_ERROR_NICK_NOT_UTF8);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_taken, DEF_MSG_INF_ERROR_NICK_TAKEN);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_restricted, DEF_MSG_INF_ERROR_NICK_RESTRICTED);
|
|
||||||
DEFAULT_STRING (msg_inf_error_cid_invalid, DEF_MSG_INF_ERROR_CID_INVALID);
|
|
||||||
DEFAULT_STRING (msg_inf_error_cid_missing, DEF_MSG_INF_ERROR_CID_MISSING);
|
|
||||||
DEFAULT_STRING (msg_inf_error_cid_taken, DEF_MSG_INF_ERROR_CID_TAKEN);
|
|
||||||
DEFAULT_STRING (msg_inf_error_pid_missing, DEF_MSG_INF_ERROR_PID_MISSING);
|
|
||||||
DEFAULT_STRING (msg_inf_error_pid_invalid, DEF_MSG_INF_ERROR_PID_INVALID);
|
|
||||||
DEFAULT_STRING (msg_ban_permanently, DEF_MSG_BAN_PERMANENTLY);
|
|
||||||
DEFAULT_STRING (msg_ban_temporarily, DEF_MSG_BAN_TEMPORARILY);
|
|
||||||
DEFAULT_STRING (msg_auth_invalid_password, DEF_MSG_AUTH_INVALID_PASSWORD);
|
|
||||||
DEFAULT_STRING (msg_auth_user_not_found, DEF_MSG_AUTH_USER_NOT_FOUND);
|
|
||||||
DEFAULT_STRING (msg_error_no_memory, DEF_MSG_ERROR_NO_MEMORY);
|
|
||||||
DEFAULT_STRING (msg_user_share_size_low, DEF_MSG_USER_SHARE_SIZE_LOW);
|
|
||||||
DEFAULT_STRING (msg_user_share_size_high, DEF_MSG_USER_SHARE_SIZE_HIGH);
|
|
||||||
DEFAULT_STRING (msg_user_slots_low, DEF_MSG_USER_SLOTS_LOW);
|
|
||||||
DEFAULT_STRING (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
|
|
||||||
DEFAULT_STRING (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
|
|
||||||
DEFAULT_STRING (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
|
|
||||||
|
|
||||||
DEFAULT_INTEGER(tls_enable, DEF_TLS_ENABLE);
|
|
||||||
DEFAULT_INTEGER(tls_require, DEF_TLS_REQUIRE);
|
|
||||||
DEFAULT_STRING (tls_certificate, DEF_TLS_CERTIFICATE);
|
|
||||||
DEFAULT_STRING (tls_private_key, DEF_TLS_PRIVATE_KEY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int apply_string(const char* key, const char* data, char** target, char* regexp)
|
||||||
static int apply_config(struct hub_config* config, char* key, char* data, int line_count)
|
|
||||||
{
|
{
|
||||||
GET_STR (file_acl);
|
(void) regexp;
|
||||||
GET_STR (file_motd);
|
// FIXME: Add regexp checks for correct data
|
||||||
GET_STR (file_rules);
|
|
||||||
GET_STR (server_bind_addr);
|
|
||||||
GET_INT (server_port);
|
|
||||||
GET_INT (server_listen_backlog);
|
|
||||||
GET_STR (server_alt_ports);
|
|
||||||
GET_STR (hub_name);
|
|
||||||
GET_STR (hub_description);
|
|
||||||
GET_BOOL(hub_enabled);
|
|
||||||
GET_INT (max_users);
|
|
||||||
GET_INT (max_chat_history);
|
|
||||||
GET_INT (max_logout_log);
|
|
||||||
GET_INT (max_recv_buffer);
|
|
||||||
GET_INT (max_send_buffer);
|
|
||||||
GET_INT (max_send_buffer_soft);
|
|
||||||
GET_BOOL(show_banner);
|
|
||||||
GET_BOOL(show_banner_sys_info);
|
|
||||||
GET_BOOL(chat_only);
|
|
||||||
GET_BOOL(chat_is_privileged);
|
|
||||||
GET_BOOL(low_bandwidth_mode);
|
|
||||||
GET_BOOL(registered_users_only);
|
|
||||||
|
|
||||||
/* Limits enforced on users */
|
if (*target)
|
||||||
GET_INT(limit_max_hubs_user);
|
hub_free(*target);
|
||||||
GET_INT(limit_max_hubs_reg);
|
|
||||||
GET_INT(limit_max_hubs_op);
|
|
||||||
GET_INT(limit_min_hubs_user);
|
|
||||||
GET_INT(limit_min_hubs_reg);
|
|
||||||
GET_INT(limit_min_hubs_op);
|
|
||||||
GET_INT(limit_max_hubs);
|
|
||||||
GET_INT(limit_min_share);
|
|
||||||
GET_INT(limit_max_share);
|
|
||||||
GET_INT(limit_min_slots);
|
|
||||||
GET_INT(limit_max_slots);
|
|
||||||
|
|
||||||
/* Status/error strings */
|
*target = hub_strdup(data);
|
||||||
GET_STR (msg_hub_full);
|
return 1;
|
||||||
GET_STR (msg_hub_disabled);
|
|
||||||
GET_STR (msg_hub_registered_users_only);
|
|
||||||
GET_STR (msg_inf_error_nick_missing);
|
|
||||||
GET_STR (msg_inf_error_nick_multiple);
|
|
||||||
GET_STR (msg_inf_error_nick_invalid);
|
|
||||||
GET_STR (msg_inf_error_nick_long);
|
|
||||||
GET_STR (msg_inf_error_nick_short);
|
|
||||||
GET_STR (msg_inf_error_nick_spaces);
|
|
||||||
GET_STR (msg_inf_error_nick_bad_chars);
|
|
||||||
GET_STR (msg_inf_error_nick_not_utf8);
|
|
||||||
GET_STR (msg_inf_error_nick_taken);
|
|
||||||
GET_STR (msg_inf_error_nick_restricted);
|
|
||||||
GET_STR (msg_inf_error_cid_invalid);
|
|
||||||
GET_STR (msg_inf_error_cid_missing);
|
|
||||||
GET_STR (msg_inf_error_cid_taken);
|
|
||||||
GET_STR (msg_inf_error_pid_missing);
|
|
||||||
GET_STR (msg_inf_error_pid_invalid);
|
|
||||||
GET_STR (msg_ban_permanently);
|
|
||||||
GET_STR (msg_ban_temporarily);
|
|
||||||
GET_STR (msg_auth_invalid_password);
|
|
||||||
GET_STR (msg_auth_user_not_found);
|
|
||||||
GET_STR (msg_error_no_memory);
|
|
||||||
GET_STR (msg_user_share_size_low);
|
|
||||||
GET_STR (msg_user_share_size_high);
|
|
||||||
GET_STR (msg_user_slots_low);
|
|
||||||
GET_STR (msg_user_slots_high);
|
|
||||||
GET_STR (msg_user_hub_limit_low);
|
|
||||||
GET_STR (msg_user_hub_limit_high);
|
|
||||||
|
|
||||||
GET_BOOL(tls_enable);
|
|
||||||
GET_BOOL(tls_require);
|
|
||||||
GET_STR (tls_certificate);
|
|
||||||
GET_STR (tls_private_key);
|
|
||||||
|
|
||||||
/* Still here -- unknown directive */
|
|
||||||
LOG_ERROR("Unknown configuration directive: '%s'", key);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int apply_integer(const char* key, const char* data, int* target, int* min, int* max)
|
||||||
void free_config(struct hub_config* config)
|
|
||||||
{
|
{
|
||||||
hub_free(config->server_bind_addr);
|
char* endptr;
|
||||||
hub_free(config->server_alt_ports);
|
int val;
|
||||||
hub_free(config->file_motd);
|
errno = 0;
|
||||||
hub_free(config->file_acl);
|
val = strtol(data, &endptr, 10);
|
||||||
hub_free(config->file_rules);
|
|
||||||
hub_free(config->hub_name);
|
|
||||||
hub_free(config->hub_description);
|
|
||||||
|
|
||||||
hub_free(config->msg_hub_full);
|
if (((errno == ERANGE && (val == INT_MAX || val == INT_MIN)) || (errno != 0 && val == 0)) || endptr == data)
|
||||||
hub_free(config->msg_hub_disabled);
|
return 0;
|
||||||
hub_free(config->msg_hub_registered_users_only);
|
|
||||||
hub_free(config->msg_inf_error_nick_missing);
|
|
||||||
hub_free(config->msg_inf_error_nick_multiple);
|
|
||||||
hub_free(config->msg_inf_error_nick_invalid);
|
|
||||||
hub_free(config->msg_inf_error_nick_long);
|
|
||||||
hub_free(config->msg_inf_error_nick_short);
|
|
||||||
hub_free(config->msg_inf_error_nick_spaces);
|
|
||||||
hub_free(config->msg_inf_error_nick_bad_chars);
|
|
||||||
hub_free(config->msg_inf_error_nick_not_utf8);
|
|
||||||
hub_free(config->msg_inf_error_nick_taken);
|
|
||||||
hub_free(config->msg_inf_error_nick_restricted);
|
|
||||||
hub_free(config->msg_inf_error_cid_invalid);
|
|
||||||
hub_free(config->msg_inf_error_cid_missing);
|
|
||||||
hub_free(config->msg_inf_error_cid_taken);
|
|
||||||
hub_free(config->msg_inf_error_pid_missing);
|
|
||||||
hub_free(config->msg_inf_error_pid_invalid);
|
|
||||||
hub_free(config->msg_ban_permanently);
|
|
||||||
hub_free(config->msg_ban_temporarily);
|
|
||||||
hub_free(config->msg_auth_invalid_password);
|
|
||||||
hub_free(config->msg_auth_user_not_found);
|
|
||||||
hub_free(config->msg_error_no_memory);
|
|
||||||
hub_free(config->msg_user_share_size_low);
|
|
||||||
hub_free(config->msg_user_share_size_high);
|
|
||||||
hub_free(config->msg_user_slots_low);
|
|
||||||
hub_free(config->msg_user_slots_high);
|
|
||||||
hub_free(config->msg_user_hub_limit_low);
|
|
||||||
hub_free(config->msg_user_hub_limit_high);
|
|
||||||
|
|
||||||
hub_free(config->tls_certificate);
|
if (min && val < *min)
|
||||||
hub_free(config->tls_private_key);
|
return 0;
|
||||||
|
|
||||||
memset(config, 0, sizeof(struct hub_config));
|
if (max && val > *max)
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
#define DUMP_STR(NAME, DEFAULT) \
|
*target = val;
|
||||||
if (ignore_defaults) \
|
return 1;
|
||||||
{ \
|
|
||||||
if (strcmp(config->NAME, DEFAULT) != 0) \
|
|
||||||
fprintf(stdout, "%s = \"%s\"\n", #NAME , config->NAME); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
fprintf(stdout, "%s = \"%s\"\n", #NAME , config->NAME); \
|
|
||||||
|
|
||||||
#define DUMP_INT(NAME, DEFAULT) \
|
|
||||||
if (ignore_defaults) \
|
|
||||||
{ \
|
|
||||||
if (config->NAME != DEFAULT) \
|
|
||||||
fprintf(stdout, "%s = %d\n", #NAME , config->NAME); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
fprintf(stdout, "%s = %d\n", #NAME , config->NAME); \
|
|
||||||
|
|
||||||
|
|
||||||
#define DUMP_BOOL(NAME, DEFAULT) \
|
|
||||||
if (ignore_defaults) \
|
|
||||||
{ \
|
|
||||||
if (config->NAME != DEFAULT) \
|
|
||||||
fprintf(stdout, "%s = %s\n", #NAME , (config->NAME ? "yes" : "no")); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
fprintf(stdout, "%s = %s\n", #NAME , (config->NAME ? "yes" : "no"));
|
|
||||||
|
|
||||||
void dump_config(struct hub_config* config, int ignore_defaults)
|
|
||||||
{
|
|
||||||
DUMP_STR (file_acl, DEF_FILE_ACL);
|
|
||||||
DUMP_STR (file_motd, DEF_FILE_MOTD);
|
|
||||||
DUMP_STR (file_rules, DEF_FILE_RULES);
|
|
||||||
DUMP_STR (server_bind_addr, DEF_SERVER_BIND_ADDR);
|
|
||||||
DUMP_INT (server_port, DEF_SERVER_PORT);
|
|
||||||
DUMP_INT (server_listen_backlog, DEF_SERVER_BACKLOG);
|
|
||||||
DUMP_STR (server_alt_ports, DEF_SERVER_ALT_PORTS);
|
|
||||||
DUMP_STR (hub_name, DEF_HUB_NAME);
|
|
||||||
DUMP_STR (hub_description, DEF_HUB_DESCRIPTION);
|
|
||||||
DUMP_BOOL(hub_enabled, DEF_HUB_ENABLED);
|
|
||||||
DUMP_INT (max_users, DEF_MAX_USERS);
|
|
||||||
DUMP_INT (max_chat_history, DEF_MAX_CHAT_HISTORY);
|
|
||||||
DUMP_INT (max_logout_log, DEF_MAX_LOGOUT_LOG);
|
|
||||||
DUMP_INT (max_recv_buffer, DEF_MAX_RECV_BUFFER);
|
|
||||||
DUMP_INT (max_send_buffer, DEF_MAX_SEND_BUFFER);
|
|
||||||
DUMP_INT (max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
|
|
||||||
DUMP_BOOL(show_banner, DEF_SHOW_BANNER);
|
|
||||||
DUMP_BOOL(show_banner_sys_info, DEF_SHOW_BANNER_SYS_INFO);
|
|
||||||
DUMP_BOOL(chat_only, DEF_CHAT_ONLY);
|
|
||||||
DUMP_BOOL(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
|
|
||||||
DUMP_BOOL(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
|
|
||||||
DUMP_BOOL(registered_users_only, DEF_REGISTERED_USERS_ONLY);
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
DUMP_BOOL(tls_enable, DEF_TLS_ENABLE);
|
|
||||||
DUMP_BOOL(tls_require, DEF_TLS_REQUIRE);
|
|
||||||
DUMP_STR (tls_certificate, DEF_TLS_CERTIFICATE);
|
|
||||||
DUMP_STR (tls_private_key, DEF_TLS_PRIVATE_KEY);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Limits enforced on users */
|
|
||||||
DUMP_INT(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
|
|
||||||
DUMP_INT(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
|
|
||||||
DUMP_INT(limit_max_hubs_op, DEF_LIMIT_MAX_HUBS_OP);
|
|
||||||
DUMP_INT(limit_min_hubs_user, DEF_LIMIT_MIN_HUBS_USER);
|
|
||||||
DUMP_INT(limit_min_hubs_reg, DEF_LIMIT_MIN_HUBS_REG);
|
|
||||||
DUMP_INT(limit_min_hubs_op, DEF_LIMIT_MIN_HUBS_OP);
|
|
||||||
DUMP_INT(limit_max_hubs, DEF_LIMIT_MAX_HUBS);
|
|
||||||
DUMP_INT(limit_min_share, DEF_LIMIT_MIN_SHARE);
|
|
||||||
DUMP_INT(limit_max_share, DEF_LIMIT_MAX_SHARE);
|
|
||||||
DUMP_INT(limit_min_slots, DEF_LIMIT_MIN_SLOTS);
|
|
||||||
DUMP_INT(limit_max_slots, DEF_LIMIT_MAX_SLOTS);
|
|
||||||
|
|
||||||
/* Status/error strings */
|
|
||||||
DUMP_STR (msg_hub_full, DEF_MSG_HUB_FULL);
|
|
||||||
DUMP_STR (msg_hub_disabled, DEF_MSG_HUB_DISABLED);
|
|
||||||
DUMP_STR (msg_hub_registered_users_only, DEF_MSG_HUB_REGISTERED_USERS_ONLY);
|
|
||||||
DUMP_STR (msg_inf_error_nick_missing, DEF_MSG_INF_ERROR_NICK_MISSING);
|
|
||||||
DUMP_STR (msg_inf_error_nick_multiple, DEF_MSG_INF_ERROR_NICK_MULTIPLE);
|
|
||||||
DUMP_STR (msg_inf_error_nick_invalid, DEF_MSG_INF_ERROR_NICK_INVALID);
|
|
||||||
DUMP_STR (msg_inf_error_nick_long, DEF_MSG_INF_ERROR_NICK_LONG);
|
|
||||||
DUMP_STR (msg_inf_error_nick_short, DEF_MSG_INF_ERROR_NICK_SHORT);
|
|
||||||
DUMP_STR (msg_inf_error_nick_spaces, DEF_MSG_INF_ERROR_NICK_SPACES);
|
|
||||||
DUMP_STR (msg_inf_error_nick_bad_chars, DEF_MSG_INF_ERROR_NICK_BAD_CHARS);
|
|
||||||
DUMP_STR (msg_inf_error_nick_not_utf8, DEF_MSG_INF_ERROR_NICK_NOT_UTF8);
|
|
||||||
DUMP_STR (msg_inf_error_nick_taken, DEF_MSG_INF_ERROR_NICK_TAKEN);
|
|
||||||
DUMP_STR (msg_inf_error_nick_restricted, DEF_MSG_INF_ERROR_NICK_RESTRICTED);
|
|
||||||
DUMP_STR (msg_inf_error_cid_invalid, DEF_MSG_INF_ERROR_CID_INVALID);
|
|
||||||
DUMP_STR (msg_inf_error_cid_missing, DEF_MSG_INF_ERROR_CID_MISSING);
|
|
||||||
DUMP_STR (msg_inf_error_cid_taken, DEF_MSG_INF_ERROR_CID_TAKEN);
|
|
||||||
DUMP_STR (msg_inf_error_pid_missing, DEF_MSG_INF_ERROR_PID_MISSING);
|
|
||||||
DUMP_STR (msg_inf_error_pid_invalid, DEF_MSG_INF_ERROR_PID_INVALID);
|
|
||||||
DUMP_STR (msg_ban_permanently, DEF_MSG_BAN_PERMANENTLY);
|
|
||||||
DUMP_STR (msg_ban_temporarily, DEF_MSG_BAN_TEMPORARILY);
|
|
||||||
DUMP_STR (msg_auth_invalid_password, DEF_MSG_AUTH_INVALID_PASSWORD);
|
|
||||||
DUMP_STR (msg_auth_user_not_found, DEF_MSG_AUTH_USER_NOT_FOUND);
|
|
||||||
DUMP_STR (msg_error_no_memory, DEF_MSG_ERROR_NO_MEMORY);
|
|
||||||
DUMP_STR (msg_user_share_size_low, DEF_MSG_USER_SHARE_SIZE_LOW);
|
|
||||||
DUMP_STR (msg_user_share_size_high, DEF_MSG_USER_SHARE_SIZE_HIGH);
|
|
||||||
DUMP_STR (msg_user_slots_low, DEF_MSG_USER_SLOTS_LOW);
|
|
||||||
DUMP_STR (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
|
|
||||||
DUMP_STR (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
|
|
||||||
DUMP_STR (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "gen_config.c"
|
||||||
|
|
||||||
static int config_parse_line(char* line, int line_count, void* ptr_data)
|
static int config_parse_line(char* line, int line_count, void* ptr_data)
|
||||||
{
|
{
|
||||||
@@ -490,10 +85,7 @@ static int config_parse_line(char* line, int line_count, void* ptr_data)
|
|||||||
char* data;
|
char* data;
|
||||||
struct hub_config* config = (struct hub_config*) ptr_data;
|
struct hub_config* config = (struct hub_config*) ptr_data;
|
||||||
|
|
||||||
if ((pos = strchr(line, '#')) != NULL)
|
strip_off_ini_line_comments(line, line_count);
|
||||||
{
|
|
||||||
pos[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*line) return 0;
|
if (!*line) return 0;
|
||||||
|
|
||||||
@@ -536,6 +128,7 @@ int read_config(const char* file, struct hub_config* config, int allow_missing)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memset(config, 0, sizeof(struct hub_config));
|
memset(config, 0, sizeof(struct hub_config));
|
||||||
|
config_defaults(config);
|
||||||
|
|
||||||
ret = file_read_lines(file, config, &config_parse_line);
|
ret = file_read_lines(file, config, &config_parse_line);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@@ -550,7 +143,6 @@ int read_config(const char* file, struct hub_config* config, int allow_missing)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config_defaults(config);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,81 +20,7 @@
|
|||||||
#ifndef HAVE_UHUB_CONFIG_H
|
#ifndef HAVE_UHUB_CONFIG_H
|
||||||
#define HAVE_UHUB_CONFIG_H
|
#define HAVE_UHUB_CONFIG_H
|
||||||
|
|
||||||
struct hub_config
|
#include "gen_config.h"
|
||||||
{
|
|
||||||
int server_port; /**<<< "Server port to bind to (default: 1511)" */
|
|
||||||
char* server_bind_addr; /**<<< "Server bind address (default: '0.0.0.0' or '::')" */
|
|
||||||
int server_listen_backlog; /**<<< "Server listen backlog (default: 50)" */
|
|
||||||
char* server_alt_ports; /**<<< "Comma separated list of alternative ports to listen to (default: '')" */
|
|
||||||
int hub_enabled; /**<<< "Is server enabled (default: 1)" */
|
|
||||||
int show_banner; /**<<< "Show banner on connect (default: 1)" */
|
|
||||||
int show_banner_sys_info; /**<<< "Show banner system information (default: 1). Has no effect unless show_banner is enabled." */
|
|
||||||
int max_users; /**<<< "Maximum number of users allowed on the hub (default: 500)" */
|
|
||||||
int registered_users_only; /**<<< "Allow registered users only (default: 0)" */
|
|
||||||
int chat_only; /**<<< "Allow chat only operation on hub (default: 0)" */
|
|
||||||
int chat_is_privileged; /**<<< "Allow chat for operators and above only (default: 0) */
|
|
||||||
char* file_motd; /**<<< "File containing the 'message of the day' (default: '' - no motd)" */
|
|
||||||
char* file_acl; /**<<< "File containing user database (default: '' - no known users)" */
|
|
||||||
char* file_rules; /**<<< "File containing the rules (default: '' - no rules)" */
|
|
||||||
char* hub_name; /**<<< "Name of hub (default: 'My uhub hub')" */
|
|
||||||
char* hub_description; /**<<< "Name of hub (default: 'no description')" */
|
|
||||||
int max_recv_buffer; /**<<< "Max read buffer before parse, per user (default: 4096)" */
|
|
||||||
int max_send_buffer; /**<<< "Max send buffer before disconnect, per user (default: 128K)" */
|
|
||||||
int max_send_buffer_soft; /**<<< "Max send buffer before message drops, per user (default: 96K)" */
|
|
||||||
int low_bandwidth_mode; /**<<< "If this is enabled, the hub will strip off elements from each user's info message to reduce bandwidth usage" */
|
|
||||||
|
|
||||||
int max_chat_history; /**<<< "Number of chat messages kept in history (default: 20)" */
|
|
||||||
int max_logout_log; /**<<< "Number of log entries for people leaving the hub. (default: 100) */
|
|
||||||
|
|
||||||
/* Limits enforced on users */
|
|
||||||
int limit_max_hubs_user; /**<<< "Max concurrent hubs as a user. (0=off, default: 10)" */
|
|
||||||
int limit_max_hubs_reg; /**<<< "Max concurrent hubs as registered user. (0=off, default: 10)" */
|
|
||||||
int limit_max_hubs_op; /**<<< "Max concurrent hubs as operator. (0=off, default: 10)" */
|
|
||||||
int limit_min_hubs_user; /**<<< "Min concurrent hubs as a user. (0=off, default: 0)" */
|
|
||||||
int limit_min_hubs_reg; /**<<< "Min concurrent hubs as registered user. (0=off, default: 0)" */
|
|
||||||
int limit_min_hubs_op; /**<<< "Min concurrent hubs as operator. (0=off, default: 0)" */
|
|
||||||
int limit_max_hubs; /**<<< "Max total hub connections allowed, user/reg/op combined. (0=off, default: 25)" */
|
|
||||||
int limit_min_share; /**<<< "Limit minimum share size in megabytes (MiB) (0=off, default: 0)" */
|
|
||||||
int limit_max_share; /**<<< "Limit maximum share size in megabytes (MiB) (0=off, default: 0)" */
|
|
||||||
int limit_min_slots; /**<<< "Limit minimum number of slots open per user (0=off, default: 0)" */
|
|
||||||
int limit_max_slots; /**<<< "Limit maximum number of slots open per user (0=off, default: 0)" */
|
|
||||||
|
|
||||||
/* Messages that can be sent to a user */
|
|
||||||
char* msg_hub_full; /**<<< "hub is full" */
|
|
||||||
char* msg_hub_disabled; /**<<< "hub is disabled" */
|
|
||||||
char* msg_hub_registered_users_only; /**<<< "hub is for registered users only" */
|
|
||||||
char* msg_inf_error_nick_missing; /**<<< "no nickname given" */
|
|
||||||
char* msg_inf_error_nick_multiple; /**<<< "multiple nicknames given" */
|
|
||||||
char* msg_inf_error_nick_invalid; /**<<< "generic/unkown" */
|
|
||||||
char* msg_inf_error_nick_long; /**<<< "nickname too long" */
|
|
||||||
char* msg_inf_error_nick_short; /**<<< "nickname too short" */
|
|
||||||
char* msg_inf_error_nick_spaces; /**<<< "nickname cannot start with spaces" */
|
|
||||||
char* msg_inf_error_nick_bad_chars; /**<<< "nickname contains chars below ascii 32" */
|
|
||||||
char* msg_inf_error_nick_not_utf8; /**<<< "nickname is not valid utf8" */
|
|
||||||
char* msg_inf_error_nick_taken; /**<<< "nickname is in use" */
|
|
||||||
char* msg_inf_error_nick_restricted; /**<<< "nickname cannot be used on this hub" */
|
|
||||||
char* msg_inf_error_cid_invalid; /**<<< "CID is not valid" */
|
|
||||||
char* msg_inf_error_cid_missing; /**<<< "CID is not specified" */
|
|
||||||
char* msg_inf_error_cid_taken; /**<<< "CID is taken" */
|
|
||||||
char* msg_inf_error_pid_missing; /**<<< "PID is not specified" */
|
|
||||||
char* msg_inf_error_pid_invalid; /**<<< "PID is invalid" */
|
|
||||||
char* msg_ban_permanently; /**<<< "Banned permanently" */
|
|
||||||
char* msg_ban_temporarily; /**<<< "Banned temporarily" */
|
|
||||||
char* msg_auth_invalid_password; /**<<< "Password is wrong" */
|
|
||||||
char* msg_auth_user_not_found; /**<<< "User not found in password database" */
|
|
||||||
char* msg_error_no_memory; /**<<< "No memory" */
|
|
||||||
char* msg_user_share_size_low; /**<<< "User is not sharing enough" */
|
|
||||||
char* msg_user_share_size_high; /**<<< "User is sharing too much" */
|
|
||||||
char* msg_user_slots_low; /**<<< "User have too few upload slots." */
|
|
||||||
char* msg_user_slots_high; /**<<< "User have too many upload slots." */
|
|
||||||
char* msg_user_hub_limit_low; /**<<< "User is on too few hubs." */
|
|
||||||
char* msg_user_hub_limit_high; /**<<< "User is on too many hubs." */
|
|
||||||
|
|
||||||
int tls_enable; /**<<< "Enable SSL/TLS support (default: 0)" */
|
|
||||||
int tls_require; /**<<< "If SSL/TLS enabled, should it be required (default: 0) */
|
|
||||||
char* tls_certificate; /**<<< "Certificate file (PEM)" */
|
|
||||||
char* tls_private_key; /**<<< "Private key" */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This initializes the configuration variables, and sets the default
|
* This initializes the configuration variables, and sets the default
|
||||||
|
|||||||
241
src/core/config.pl
Executable file
241
src/core/config.pl
Executable file
@@ -0,0 +1,241 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use XML::Twig;
|
||||||
|
|
||||||
|
sub write_c_header(@);
|
||||||
|
sub write_c_impl_defaults(@);
|
||||||
|
sub write_c_impl_apply(@);
|
||||||
|
sub write_c_impl_free(@);
|
||||||
|
sub write_c_impl_dump(@);
|
||||||
|
sub get_data($);
|
||||||
|
|
||||||
|
# initialize parser and read the file
|
||||||
|
my $input = "./config.xml";
|
||||||
|
my $parser = XML::Twig->new();
|
||||||
|
my $tree = $parser->parsefile($input) || die "Unable to parse XML file.";
|
||||||
|
|
||||||
|
# Write header file
|
||||||
|
open GENHEAD, ">gen_config.h" || die "Unable to write header file";
|
||||||
|
print GENHEAD "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\nstruct hub_config\n{\n";
|
||||||
|
foreach my $p ($tree->root->children("option"))
|
||||||
|
{
|
||||||
|
write_c_header(get_data($p));
|
||||||
|
}
|
||||||
|
print GENHEAD "};\n\n";
|
||||||
|
|
||||||
|
# Write c source file
|
||||||
|
open GENIMPL, ">gen_config.c" || die "Unable to write source file";
|
||||||
|
print GENIMPL "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\n";
|
||||||
|
|
||||||
|
# The defaults function
|
||||||
|
print GENIMPL "void config_defaults(struct hub_config* config)\n{\n";
|
||||||
|
foreach my $p ($tree->root->children("option"))
|
||||||
|
{
|
||||||
|
write_c_impl_defaults(get_data($p));
|
||||||
|
}
|
||||||
|
print GENIMPL "}\n\n";
|
||||||
|
|
||||||
|
# apply function
|
||||||
|
print GENIMPL "static int apply_config(struct hub_config* config, char* key, char* data, int line_count)\n{\n\tint max = 0;\n\tint min = 0;\n\n";
|
||||||
|
|
||||||
|
foreach my $p ($tree->root->children("option"))
|
||||||
|
{
|
||||||
|
write_c_impl_apply(get_data($p));
|
||||||
|
}
|
||||||
|
print GENIMPL "\t/* Still here -- unknown directive */\n";
|
||||||
|
print GENIMPL "\tLOG_ERROR(\"Unknown configuration directive: '%s'\", key);\n";
|
||||||
|
print GENIMPL "\t\treturn -1;\n";
|
||||||
|
print GENIMPL "}\n\n";
|
||||||
|
|
||||||
|
# free function (for strings)
|
||||||
|
print GENIMPL "void free_config(struct hub_config* config)\n{\n";
|
||||||
|
foreach my $p ($tree->root->children("option"))
|
||||||
|
{
|
||||||
|
write_c_impl_free(get_data($p));
|
||||||
|
}
|
||||||
|
print GENIMPL "}\n\n";
|
||||||
|
|
||||||
|
# dump function
|
||||||
|
print GENIMPL "void dump_config(struct hub_config* config, int ignore_defaults)\n{\n";
|
||||||
|
foreach my $p ($tree->root->children("option"))
|
||||||
|
{
|
||||||
|
write_c_impl_dump(get_data($p));
|
||||||
|
}
|
||||||
|
print GENIMPL "}\n\n";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sub write_c_header(@)
|
||||||
|
{
|
||||||
|
my @output = @_;
|
||||||
|
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
|
||||||
|
|
||||||
|
print GENHEAD "\t";
|
||||||
|
print GENHEAD "int " if ($type eq "int");
|
||||||
|
print GENHEAD "int " if ($type eq "boolean");
|
||||||
|
print GENHEAD "char*" if ($type =~ /(string|file|message)/);
|
||||||
|
print GENHEAD " " . $name . ";";
|
||||||
|
|
||||||
|
my $comment = "";
|
||||||
|
if ($type eq "message")
|
||||||
|
{
|
||||||
|
$comment = "\"" . $default . "\"";
|
||||||
|
}
|
||||||
|
elsif (defined $short && length $short > 0)
|
||||||
|
{
|
||||||
|
$comment = $short;
|
||||||
|
$comment .= " (default: " . $default . ")" if (defined $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length $comment > 0)
|
||||||
|
{
|
||||||
|
my $pad = "";
|
||||||
|
for (my $i = length $name; $i < 32; $i++)
|
||||||
|
{
|
||||||
|
$pad .= " ";
|
||||||
|
}
|
||||||
|
$comment = $pad . "/*<<< " . $comment . " */";
|
||||||
|
}
|
||||||
|
|
||||||
|
print GENHEAD $comment . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub write_c_impl_defaults(@)
|
||||||
|
{
|
||||||
|
my @output = @_;
|
||||||
|
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
|
||||||
|
my $prefix = "";
|
||||||
|
my $suffix = "";
|
||||||
|
|
||||||
|
print GENIMPL "\tconfig->$name = ";
|
||||||
|
if ($type =~ /(string|file|message)/)
|
||||||
|
{
|
||||||
|
$prefix = "hub_strdup(\"";
|
||||||
|
$suffix = "\")"
|
||||||
|
}
|
||||||
|
print GENIMPL $prefix . $default . $suffix . ";\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub write_c_impl_apply(@)
|
||||||
|
{
|
||||||
|
my @output = @_;
|
||||||
|
my ($type, $name, $default, $advanced, $short, $desc, $since, $example, $p) = @output;
|
||||||
|
|
||||||
|
my $min;
|
||||||
|
my $max;
|
||||||
|
my $regexp;
|
||||||
|
|
||||||
|
if (defined $p)
|
||||||
|
{
|
||||||
|
$min = $p->att("min");
|
||||||
|
$max = $p->att("max");
|
||||||
|
$regexp = $p->att("regexp");
|
||||||
|
|
||||||
|
print "'check' is defined for option $name";
|
||||||
|
print ", min=$min" if (defined $min);
|
||||||
|
print ", max=$max" if (defined $max);
|
||||||
|
print ", regexp=\"$regexp\"" if (defined $regexp);
|
||||||
|
print "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
print GENIMPL "\tif (!strcmp(key, \"" . $name . "\"))\n\t{\n";
|
||||||
|
|
||||||
|
if ($type eq "int")
|
||||||
|
{
|
||||||
|
if (defined $min)
|
||||||
|
{
|
||||||
|
print GENIMPL "\t\tmin = $min;\n"
|
||||||
|
}
|
||||||
|
if (defined $max)
|
||||||
|
{
|
||||||
|
print GENIMPL "\t\tmax = $max;\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
print GENIMPL "\t\tif (!apply_integer(key, data, &config->$name, ";
|
||||||
|
|
||||||
|
if (defined $min)
|
||||||
|
{
|
||||||
|
print GENIMPL "&min";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print GENIMPL "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
print GENIMPL ", ";
|
||||||
|
|
||||||
|
if (defined $max)
|
||||||
|
{
|
||||||
|
print GENIMPL "&max";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print GENIMPL "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
print GENIMPL "))\n";
|
||||||
|
}
|
||||||
|
elsif ($type eq "boolean")
|
||||||
|
{
|
||||||
|
print GENIMPL "\t\tif (!apply_boolean(key, data, &config->$name))\n";
|
||||||
|
}
|
||||||
|
elsif ($type =~ /(string|file|message)/)
|
||||||
|
{
|
||||||
|
print GENIMPL "\t\tif (!apply_string(key, data, &config->$name, (char*) \"\"))\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
print GENIMPL "\t\t{\n" .
|
||||||
|
"\t\t\tLOG_ERROR(\"Configuration parse error on line %d\", line_count);\n" .
|
||||||
|
"\t\t\treturn -1;\n" .
|
||||||
|
"\t\t}\n" .
|
||||||
|
"\t\treturn 0;\n" .
|
||||||
|
"\t}\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub write_c_impl_free(@)
|
||||||
|
{
|
||||||
|
my @output = @_;
|
||||||
|
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
|
||||||
|
|
||||||
|
if ($type =~ /(string|file|message)/)
|
||||||
|
{
|
||||||
|
print GENIMPL "\thub_free(config->" . $name . ");\n\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub write_c_impl_dump(@)
|
||||||
|
{
|
||||||
|
my @output = @_;
|
||||||
|
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
|
||||||
|
my $out;
|
||||||
|
my $val = "config->$name";
|
||||||
|
my $test = "config->$name != $default";
|
||||||
|
|
||||||
|
if ($type eq "int")
|
||||||
|
{
|
||||||
|
$out = "%d";
|
||||||
|
}
|
||||||
|
elsif ($type eq "boolean")
|
||||||
|
{
|
||||||
|
$out = "%s";
|
||||||
|
$val = "config->$name ? \"yes\" : \"no\"";
|
||||||
|
}
|
||||||
|
elsif ($type =~ /(string|file|message)/)
|
||||||
|
{
|
||||||
|
$out = "\\\"%s\\\"";
|
||||||
|
$test = "strcmp(config->$name, \"$default\") != 0";
|
||||||
|
}
|
||||||
|
|
||||||
|
print GENIMPL "\tif (!ignore_defaults || $test)\n";
|
||||||
|
print GENIMPL "\t\tfprintf(stdout, \"$name = $out\\n\", $val);\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_data($)
|
||||||
|
{
|
||||||
|
my $p = shift;
|
||||||
|
my $check = $p->first_child_matches("check");
|
||||||
|
my @data = ($p->att("type"), $p->att("name"), $p->att("default"), $p->att("advanced"), $p->children_text("short"), $p->children_text("description"), $p->children_text("since"), $p->children_text("example"), $check);
|
||||||
|
return @data;
|
||||||
|
}
|
||||||
|
|
||||||
687
src/core/config.xml
Normal file
687
src/core/config.xml
Normal file
@@ -0,0 +1,687 @@
|
|||||||
|
<?xml version='1.0' standalone="yes" ?>
|
||||||
|
<config>
|
||||||
|
|
||||||
|
<option name="hub_enabled" type="boolean" default="1">
|
||||||
|
<short>Is server enabled</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Use this to disable the hub for a while.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.3</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="server_port" type="int" default="1511">
|
||||||
|
<check min="1" max="65535" />
|
||||||
|
<since>0.1.0</since>
|
||||||
|
<short>Server port to bind to</short>
|
||||||
|
<description><![CDATA[This is specifies the port number the hub should listen on.]]></description>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="server_bind_addr" type="string" default="any">
|
||||||
|
<check regexp="(\d\.\d\.\d\.\d\)|(any)|(loopback)|(.*)" /><!-- FIXME: add better IPv6 regexp in the future! -->
|
||||||
|
<short>Server bind address</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Specify the IP address the local hub should bind to. This can be an IPv4 or IPv6 address, or one of the special addresses "any" or "loopback". <br />
|
||||||
|
When "any" or "loopback" is used, the hub will automatically detect if IPv6 is supported and prefer that.
|
||||||
|
]]></description>
|
||||||
|
<syntax>
|
||||||
|
IPv4 address, IPv6 address, "any" or "loopback"
|
||||||
|
</syntax>
|
||||||
|
<since>0.1.2</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
<p>
|
||||||
|
To listen to a specific IP:<br />
|
||||||
|
server_bind_addr = "192.168.12.69"
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
To listen to any IPv4 address:<br />
|
||||||
|
server_bind_addr = "0.0.0.0"
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Or to listen to any address including IPv6 (if supported):<br />
|
||||||
|
server_bind_addr = "any"
|
||||||
|
</p>
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="server_listen_backlog" type="int" default="50">
|
||||||
|
<check min="5" />
|
||||||
|
<short>Server listen backlog</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
<p>
|
||||||
|
This specifies the number of connections the hub will be able to accept in the backlog before they must be processed by the hub.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
A too low number here will mean the hub will not accept connections fast enough when users are reconnecting really fast. The hub should under normal circumstances be able to empty the listen backlog several times per second.
|
||||||
|
</p>
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="server_alt_ports" type="string" default="">
|
||||||
|
<check regexp="((\d+)(,(\d+))*)?" />
|
||||||
|
<short>Comma separated list of alternative ports to listen to</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
In addition to the server_port the hub can listen to a list of alternative ports.
|
||||||
|
]]></description>
|
||||||
|
<example><![CDATA[
|
||||||
|
server_alt_ports = 1295,1512,53990
|
||||||
|
]]></example>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="show_banner" type="boolean" default="1">
|
||||||
|
<short>Show banner on connect</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If enabled, the hub will announce the software version running to clients when they connect with a message like: "Powered by uhub/0.x.y"
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="show_banner_sys_info" type="boolean" default="1">
|
||||||
|
<short>Show banner on connect</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If enabled, the hub will announce the operating system and CPU architecture to clients when they join.<br />
|
||||||
|
This option has no effect if show_banner is disabled.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="max_users" type="int" default="500">
|
||||||
|
<check min="1" max="1048576" />
|
||||||
|
<short>Maximum number of users allowed on the hub</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
The maximum amount of users allowed on the hub.
|
||||||
|
No new users will be allowed to enter the hub if this number is exceeded, however privileged users (operators, admins, etc) are still able to log in.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.0</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
To run a hub for max 25 users:<br />
|
||||||
|
max_users = 25
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="registered_users_only" type="boolean" default="0">
|
||||||
|
<short>Allow registered users only</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is enabled only registered users will be able to use the hub. A user must be registered in the acl file (file_acl).
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="obsolete_clients" type="boolean" default="0">
|
||||||
|
<short>Support obsolete clients using a ADC protocol prior to 1.0</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is enabled users using old ADC clients are allowed to enter the hub,
|
||||||
|
however they cannot log in using passwords since the protocols are incompatible.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="chat_only" type="boolean" default="0">
|
||||||
|
<short>Allow chat only operation on hub</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is enabled the hub will refuse to relay messages for search and connection setup. This effectively makes the hub viable for chat only.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="chat_is_privileged" type="boolean" default="0">
|
||||||
|
<short>Allow chat for operators and above only</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If enabled only operators and admins are allowed to chat in the main chat.
|
||||||
|
]]></description>
|
||||||
|
<since>0.2.4</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="hub_name" type="string" default="uhub">
|
||||||
|
<short>Name of hub</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Configures the name of the hub
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.0</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
hub_name = "my hub"
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="hub_description" type="string" default="no description">
|
||||||
|
<short>Short hub description, topic or subject.</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This is the description of the hub, as seen by users and hub lists.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.0</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
hub_description = "a friendly hub for friendly people"
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="redirect_addr" type="string" default="">
|
||||||
|
<check regexp="(adc|adcs|dchub)://.*" />
|
||||||
|
<short>A common hub redirect address.</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This is the redirect address used when the hub wants to redirect a client for not fulfilling some requirements.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.2</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
|
||||||
|
<option name="max_recv_buffer" type="int" default="4096" advanced="true" >
|
||||||
|
<check min="1024" max="1048576" />
|
||||||
|
<short>Max read buffer before parse, per user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Maximum receive buffer allowed before commands are procesed. If a single ADC message exceeds this limit, it will be discarded by the hub. Use with caution.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.3</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="max_send_buffer" type="int" default="131072" advanced="true" >
|
||||||
|
<check min="2048" />
|
||||||
|
<short>Max send buffer before disconnect, per user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Maximum amount of bytes allowed to be queued for sending to any particular user before the hub will disconnect the user. The lower the limit, the more aggressive the hub will be to disconnect slow clients. Use with caution.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.3</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="max_send_buffer_soft" type="int" default="98304" advanced="true" >
|
||||||
|
<check min="1024" />
|
||||||
|
<short>Max send buffer before message drops, per user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Same as max_send_buffer, however low priority messages may be discarded if this limit is reached. Use with caution.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.3</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="low_bandwidth_mode" type="boolean" default="0" advanced="true" >
|
||||||
|
<short>Enable bandwidth saving measures</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is enabled the hub will remove excessive information from each user's info message before broadcasting to all connected users.
|
||||||
|
Description, e-mail address will be removed. This saves upload bandwidth for the hub.
|
||||||
|
]]></description>
|
||||||
|
<since>0.2.2</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="max_chat_history" type="int" default="20">
|
||||||
|
<check min="0" max="250" />
|
||||||
|
<short>Number of chat messages kept in history</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This specifies the number of main chat messages that are kept in the history buffer.
|
||||||
|
Users can use the "!history" command to list these messages.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="max_logout_log" type="int" default="20">
|
||||||
|
<check min="0" max="2000" />
|
||||||
|
<short>Number of log entries for people leaving the hub</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Operators can use the "!log" command to list users who have recently left the hub.
|
||||||
|
This option specifies the maximum size of this log.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_max_hubs_user" type="int" default="10">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Max concurrent hubs as a guest user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This limits the number of hubs a user can be logged into as a guest user. If this number is exceeded, the user will not be allowed to enter the hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_max_hubs_reg" type="int" default="10">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Max concurrent hubs as a registered user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This limits the number of hubs a user can be logged into as a registered user. If this number is exceeded, the user will not be allowed to enter the hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_max_hubs_op" type="int" default="10">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Max concurrent hubs as a operator (or admin)</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This limits the number of hubs a user can be logged into as an operator. If this number is exceeded, the user will not be allowed to enter the hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_max_hubs" type="int" default="25">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Max total hub connections allowed, user/reg/op combined.</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Limit the number of hubs a user can be logged into in total regardless of registrations or privileges.
|
||||||
|
If this number is exceeded, the user will not be allowed to enter the hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_min_hubs_user" type="int" default="0">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Minimum concurrent hubs as a guest user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Only allow users that are logged into other hubs with guest privileges to enter this hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_min_hubs_reg" type="int" default="0">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Minimum concurrent hubs as a registered user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Only allow users that are logged into other hubs as a registered user to enter this hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_min_hubs_op" type="int" default="0">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Minimum concurrent hubs as a operator (or admin)</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Only allow users that are logged into other hubs with operator privileges to enter this hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_min_share" type="int" default="0">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Limit minimum share size in megabytes</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Minimum share limit in megabytes (MiB). Users sharing less than this will not be allowed to enter the hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
To require users to share at least 1 GB in order to enter the hub:<br />
|
||||||
|
limit_min_share = 1024
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_max_share" type="int" default="0">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Limit maximum share size in megabytes</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Maximum share limit in megabytes (MiB). Users sharing more than this will not be allowed to enter the hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
|
||||||
|
<option name="limit_min_slots" type="int" default="0">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Limit minimum number of upload slots open per user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Minimum number of upload slots required. Users with less than this will not be allowed to enter the hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_max_slots" type="int" default="0">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Limit minimum number of upload slots open per user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Maximum number of upload slots allowed. Users with more than this will not be allowed to enter the hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="flood_ctl_interval" type="int" default="0">
|
||||||
|
<check min="1" max="60" />
|
||||||
|
<short>Time interval in seconds for flood control check.</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This is the time interval that will be used for all flood control calculations.
|
||||||
|
If this is 0 then all flood control is disabled.
|
||||||
|
]]></description>
|
||||||
|
<example><![CDATA[
|
||||||
|
To limit maximum chat messages to 5 messages on 10 seconds: <br />
|
||||||
|
flood_ctl_interval = 10 <br />
|
||||||
|
flood_ctl_chat = 5<br />
|
||||||
|
]]></example>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="flood_ctl_chat" type="int" default="0">
|
||||||
|
<short>Max chat messages allowed in time interval</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is 0 then no flood control is disabled for chat messages.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="flood_ctl_connect" type="int" default="0">
|
||||||
|
<short>Max connections requests allowed in time interval</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is 0 then no flood control is disabled for connection requests.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="flood_ctl_search" type="int" default="0">
|
||||||
|
<short>Max search requests allowed in time interval</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is 0 then no flood control is disabled for search requests.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
|
||||||
|
<option name="flood_ctl_update" type="int" default="0">
|
||||||
|
<short>Max updates allowed in time interval</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is 0 then no flood control is disabled for info updates (INF messages).
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="flood_ctl_extras" type="int" default="0">
|
||||||
|
<short>Max extra messages allowed in time interval</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Extra messages are messages that don't fit into the category of chat, search, update or connect.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="tls_enable" type="boolean" default="0">
|
||||||
|
<short>Enable SSL/TLS support</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Enables/disables TLS/SSL support. tls_certificate and tls_private_key must be set if this is enabled.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="tls_require" type="boolean" default="0">
|
||||||
|
<short>If SSL/TLS enabled, should it be required (default: 0)</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If TLS/SSL support is enabled it can either be optional or mandatory.
|
||||||
|
If this option is disabled then SSL/TLS is not required to enter the hub, however it is possible to enter either with or without.
|
||||||
|
This option has no effect unless tls_enable is enabled.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="tls_certificate" type="file" default="">
|
||||||
|
<short>Certificate file</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Path to a TLS/SSL certificate (PEM format).
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="tls_private_key" type="file" default="">
|
||||||
|
<short>Private key file</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Path to a TLS/SSL private key (PEM format).
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="file_motd" type="file" default="">
|
||||||
|
<short>File containing the 'message of the day</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This can be specified as a message of the day file. If a valid file is given here it's content will be sent to all users after they have logged in to the hub. If the file is missing or empty this configuration entry will be ignored.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.3</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
<p>
|
||||||
|
Unix users: <br />
|
||||||
|
file_acl = "/etc/uhub/motd.txt"
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Windows users: <br />
|
||||||
|
file_acl = "c:\uhub\motd.txt"
|
||||||
|
</p>
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="file_acl" type="file" default="">
|
||||||
|
<short>File containing access control lists</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This is an access control list (acl) file.
|
||||||
|
In this file all registered users, bans, etc should be stored.
|
||||||
|
If the file is missing, or empty no registered users, or ban records are used.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.3</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
<p>
|
||||||
|
Unix users: <br />
|
||||||
|
file_acl = "/etc/uhub/users.conf"
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Windows users: <br />
|
||||||
|
file_acl = "c:\uhub\users.conf"
|
||||||
|
</p>
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="file_rules" type="file" default="">
|
||||||
|
<short>File containing hub rules</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This is a text file that is displayed on login as an extended message of the day.
|
||||||
|
In addition the contents of the file is displayed when a user uses the "!rules" command.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
<p>
|
||||||
|
Unix users: <br />
|
||||||
|
file_acl = "/etc/uhub/rules.txt"
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Windows users: <br />
|
||||||
|
file_acl = "c:\uhub\rules.txt"
|
||||||
|
</p>
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="file_plugins" type="file" default="">
|
||||||
|
<short>Plugin configuration file</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Plugin configuration file.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.3</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
<p>
|
||||||
|
file_plugins = "/etc/uhub/plugins.conf"
|
||||||
|
</p>
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_hub_full" type="message" default="Hub is full" >
|
||||||
|
<description><![CDATA[This will be sent if the hub is full]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_hub_disabled" type="message" default="Hub is disabled" >
|
||||||
|
<description><![CDATA[This will be sent if the hub is disabled (hub_enable = off)]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_hub_registered_users_only" type="message" default="Hub is for registered users only" >
|
||||||
|
<description><![CDATA[This will be sent if the hub is configured to only accept registered users (registered_users_only = yes)]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_missing" type="message" default="No nickname given">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that do not provide a nickname.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_multiple" type="message" default="Multiple nicknames given">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provide multiple nicknames.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_invalid" type="message" default="Nickname is invalid">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides an invalid nickname.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_long" type="message" default="Nickname too long">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides a too long nickname.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_short" type="message" default="Nickname too short">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides a too short nickname.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_spaces" type="message" default="Nickname cannot start with spaces">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides a nickname that starts with a space.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_bad_chars" type="message" default="Nickname contains invalid characters">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides invalid characters in the nickname.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_not_utf8" type="message" default="Nickname is not valid UTF-8">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides a nick name that is not valid UTF-8 encoded.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_taken" type="message" default="Nickname is already in use">
|
||||||
|
<description><![CDATA[This message will be sent to clients if their provided nickname is alredy in use on the hub.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_restricted" type="message" default="Nickname cannot be used on this hub">
|
||||||
|
<description><![CDATA[This message will be sent to clients if they provide a restricted nickname. Restricted names can be configured in the acl.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_cid_invalid" type="message" default="CID is not valid">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides an invalid client ID (CID)]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_cid_missing" type="message" default="CID is not specified">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that does not provide a client ID (CID)]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_cid_taken" type="message" default="CID is taken">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides a client ID (CID) already in use on the hub.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_pid_missing" type="message" default="PID is not specified">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that does not provide a private ID (PID)]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_pid_invalid" type="message" default="PID is invalid">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides an invalid private ID (PID)]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_ban_permanently" type="message" default="Banned permanently">
|
||||||
|
<description><![CDATA[This message is sent to users if they are banned (see acl)]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_ban_temporarily" type="message" default="Banned temporarily">
|
||||||
|
<description><![CDATA[This message is sent to users if they are banned temporarily]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
|
||||||
|
<option name="msg_auth_invalid_password" type="message" default="Password is wrong">
|
||||||
|
<description><![CDATA[This message is sent to users if they provide a wrong password.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_auth_user_not_found" type="message" default="User not found in password database">
|
||||||
|
<description><![CDATA[This message is used if a user cannot be found in the password database.]]></description>
|
||||||
|
<since>0.2.0</since> <!-- FIXME? -->
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_error_no_memory" type="message" default="No memory">
|
||||||
|
<description><![CDATA[]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_share_size_low" type="message" default="User is not sharing enough">
|
||||||
|
<description><![CDATA[This message is sent to users if they are not sharing enough.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_share_size_high" type="message" default="User is sharing too much">
|
||||||
|
<description><![CDATA[This message is sent to users if they are sharing too much.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_slots_low" type="message" default="User have too few upload slots.">
|
||||||
|
<description><![CDATA[This message is sent to users if they do not have enough upload slots.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_slots_high" type="message" default="User have too many upload slots.">
|
||||||
|
<description><![CDATA[This message is sent to users if they have too many upload slots.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_hub_limit_low" type="message" default="User is on too few hubs.">
|
||||||
|
<description><![CDATA[This message is sent to users if they are on too few other hubs.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_hub_limit_high" type="message" default="User is on too many hubs.">
|
||||||
|
<description><![CDATA[This message is sent to users if they are on too many other hubs.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_flood_chat" type="message" default="Chat flood detected, messages are dropped.">
|
||||||
|
<description><![CDATA[This message is sent once to users who are flooding the chat.]]></description>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_flood_connect" type="message" default="Connect flood detected, connection refused.">
|
||||||
|
<description><![CDATA[This message is sent once to users who are sending too many connect requests too fast.]]></description>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_flood_search" type="message" default="Search flood detected, search is stopped.">
|
||||||
|
<description><![CDATA[This message is sent once to users who are sending too many search requests too fast.]]></description>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_flood_update" type="message" default="Update flood detected.">
|
||||||
|
<description><![CDATA[This message is sent once to users who are sending too many updates too fast.]]></description>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_flood_extras" type="message" default="Flood detected.">
|
||||||
|
<description><![CDATA[This message is sent once to users who are sending too many messages to the hub that neither are chat, searhes, updates nor connection requests..]]></description>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_proto_no_common_hash" type="message" default="No common hash algorithm.">
|
||||||
|
<description><![CDATA[This message is sent if a client connects that does support ADC/1.0 but not a hash algorithm that the hub supports.]]></description>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_proto_obsolete_adc0" type="message" default="Client is using an obsolete ADC protocol version.">
|
||||||
|
<description><![CDATA[This message is sent if a client connects that does not support ADC/1.0, but rather the obsolete ADC/0.1 version.]]></description>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
</config>
|
||||||
55
src/core/floodctl.c
Normal file
55
src/core/floodctl.c
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
void flood_control_reset(struct flood_control* data)
|
||||||
|
{
|
||||||
|
memset(data, 0, sizeof(struct flood_control));
|
||||||
|
}
|
||||||
|
|
||||||
|
int flood_control_check(struct flood_control* data, size_t max_count, size_t time_delay, time_t now)
|
||||||
|
{
|
||||||
|
// Is flood control disabled?
|
||||||
|
if (!time_delay || !max_count)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!data->time)
|
||||||
|
{
|
||||||
|
data->time = now;
|
||||||
|
data->count = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((now - data->time) > time_delay)
|
||||||
|
{
|
||||||
|
data->time = now;
|
||||||
|
data->count = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->count <= max_count)
|
||||||
|
{
|
||||||
|
data->count++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
47
src/core/floodctl.h
Normal file
47
src/core/floodctl.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_UHUB_FLOOD_CTL_H
|
||||||
|
#define HAVE_UHUB_FLOOD_CTL_H
|
||||||
|
|
||||||
|
struct flood_control
|
||||||
|
{
|
||||||
|
time_t time;
|
||||||
|
size_t count;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset flood control statistics
|
||||||
|
*/
|
||||||
|
void flood_control_reset(struct flood_control*);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ctl Flood control data structure
|
||||||
|
* @param max_count Max count for flood control
|
||||||
|
* @param window Time window for max_count to appear.
|
||||||
|
* @param now The current time.
|
||||||
|
*
|
||||||
|
* @return 0 if flood no flood detected.
|
||||||
|
* 1 if flood detected.
|
||||||
|
*/
|
||||||
|
int flood_control_check(struct flood_control* ctl, size_t max_count, size_t window, time_t now);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_FLOOD_CTL_H */
|
||||||
|
|
||||||
1271
src/core/gen_config.c
Normal file
1271
src/core/gen_config.c
Normal file
File diff suppressed because it is too large
Load Diff
88
src/core/gen_config.h
Normal file
88
src/core/gen_config.h
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */
|
||||||
|
|
||||||
|
struct hub_config
|
||||||
|
{
|
||||||
|
int hub_enabled; /*<<< Is server enabled (default: 1) */
|
||||||
|
int server_port; /*<<< Server port to bind to (default: 1511) */
|
||||||
|
char* server_bind_addr; /*<<< Server bind address (default: any) */
|
||||||
|
int server_listen_backlog; /*<<< Server listen backlog (default: 50) */
|
||||||
|
char* server_alt_ports; /*<<< Comma separated list of alternative ports to listen to (default: ) */
|
||||||
|
int show_banner; /*<<< Show banner on connect (default: 1) */
|
||||||
|
int show_banner_sys_info; /*<<< Show banner on connect (default: 1) */
|
||||||
|
int max_users; /*<<< Maximum number of users allowed on the hub (default: 500) */
|
||||||
|
int registered_users_only; /*<<< Allow registered users only (default: 0) */
|
||||||
|
int obsolete_clients; /*<<< Support obsolete clients using a ADC protocol prior to 1.0 (default: 0) */
|
||||||
|
int chat_only; /*<<< Allow chat only operation on hub (default: 0) */
|
||||||
|
int chat_is_privileged; /*<<< Allow chat for operators and above only (default: 0) */
|
||||||
|
char* hub_name; /*<<< Name of hub (default: uhub) */
|
||||||
|
char* hub_description; /*<<< Short hub description, topic or subject. (default: no description) */
|
||||||
|
char* redirect_addr; /*<<< A common hub redirect address. (default: ) */
|
||||||
|
int max_recv_buffer; /*<<< Max read buffer before parse, per user (default: 4096) */
|
||||||
|
int max_send_buffer; /*<<< Max send buffer before disconnect, per user (default: 131072) */
|
||||||
|
int max_send_buffer_soft; /*<<< Max send buffer before message drops, per user (default: 98304) */
|
||||||
|
int low_bandwidth_mode; /*<<< Enable bandwidth saving measures (default: 0) */
|
||||||
|
int max_chat_history; /*<<< Number of chat messages kept in history (default: 20) */
|
||||||
|
int max_logout_log; /*<<< Number of log entries for people leaving the hub (default: 20) */
|
||||||
|
int limit_max_hubs_user; /*<<< Max concurrent hubs as a guest user (default: 10) */
|
||||||
|
int limit_max_hubs_reg; /*<<< Max concurrent hubs as a registered user (default: 10) */
|
||||||
|
int limit_max_hubs_op; /*<<< Max concurrent hubs as a operator (or admin) (default: 10) */
|
||||||
|
int limit_max_hubs; /*<<< Max total hub connections allowed, user/reg/op combined. (default: 25) */
|
||||||
|
int limit_min_hubs_user; /*<<< Minimum concurrent hubs as a guest user (default: 0) */
|
||||||
|
int limit_min_hubs_reg; /*<<< Minimum concurrent hubs as a registered user (default: 0) */
|
||||||
|
int limit_min_hubs_op; /*<<< Minimum concurrent hubs as a operator (or admin) (default: 0) */
|
||||||
|
int limit_min_share; /*<<< Limit minimum share size in megabytes (default: 0) */
|
||||||
|
int limit_max_share; /*<<< Limit maximum share size in megabytes (default: 0) */
|
||||||
|
int limit_min_slots; /*<<< Limit minimum number of upload slots open per user (default: 0) */
|
||||||
|
int limit_max_slots; /*<<< Limit minimum number of upload slots open per user (default: 0) */
|
||||||
|
int flood_ctl_interval; /*<<< Time interval in seconds for flood control check. (default: 0) */
|
||||||
|
int flood_ctl_chat; /*<<< Max chat messages allowed in time interval (default: 0) */
|
||||||
|
int flood_ctl_connect; /*<<< Max connections requests allowed in time interval (default: 0) */
|
||||||
|
int flood_ctl_search; /*<<< Max search requests allowed in time interval (default: 0) */
|
||||||
|
int flood_ctl_update; /*<<< Max updates allowed in time interval (default: 0) */
|
||||||
|
int flood_ctl_extras; /*<<< Max extra messages allowed in time interval (default: 0) */
|
||||||
|
int tls_enable; /*<<< Enable SSL/TLS support (default: 0) */
|
||||||
|
int tls_require; /*<<< If SSL/TLS enabled, should it be required (default: 0) (default: 0) */
|
||||||
|
char* tls_certificate; /*<<< Certificate file (default: ) */
|
||||||
|
char* tls_private_key; /*<<< Private key file (default: ) */
|
||||||
|
char* file_motd; /*<<< File containing the 'message of the day (default: ) */
|
||||||
|
char* file_acl; /*<<< File containing access control lists (default: ) */
|
||||||
|
char* file_rules; /*<<< File containing hub rules (default: ) */
|
||||||
|
char* file_plugins; /*<<< Plugin configuration file (default: ) */
|
||||||
|
char* msg_hub_full; /*<<< "Hub is full" */
|
||||||
|
char* msg_hub_disabled; /*<<< "Hub is disabled" */
|
||||||
|
char* msg_hub_registered_users_only; /*<<< "Hub is for registered users only" */
|
||||||
|
char* msg_inf_error_nick_missing; /*<<< "No nickname given" */
|
||||||
|
char* msg_inf_error_nick_multiple; /*<<< "Multiple nicknames given" */
|
||||||
|
char* msg_inf_error_nick_invalid; /*<<< "Nickname is invalid" */
|
||||||
|
char* msg_inf_error_nick_long; /*<<< "Nickname too long" */
|
||||||
|
char* msg_inf_error_nick_short; /*<<< "Nickname too short" */
|
||||||
|
char* msg_inf_error_nick_spaces; /*<<< "Nickname cannot start with spaces" */
|
||||||
|
char* msg_inf_error_nick_bad_chars; /*<<< "Nickname contains invalid characters" */
|
||||||
|
char* msg_inf_error_nick_not_utf8; /*<<< "Nickname is not valid UTF-8" */
|
||||||
|
char* msg_inf_error_nick_taken; /*<<< "Nickname is already in use" */
|
||||||
|
char* msg_inf_error_nick_restricted; /*<<< "Nickname cannot be used on this hub" */
|
||||||
|
char* msg_inf_error_cid_invalid; /*<<< "CID is not valid" */
|
||||||
|
char* msg_inf_error_cid_missing; /*<<< "CID is not specified" */
|
||||||
|
char* msg_inf_error_cid_taken; /*<<< "CID is taken" */
|
||||||
|
char* msg_inf_error_pid_missing; /*<<< "PID is not specified" */
|
||||||
|
char* msg_inf_error_pid_invalid; /*<<< "PID is invalid" */
|
||||||
|
char* msg_ban_permanently; /*<<< "Banned permanently" */
|
||||||
|
char* msg_ban_temporarily; /*<<< "Banned temporarily" */
|
||||||
|
char* msg_auth_invalid_password; /*<<< "Password is wrong" */
|
||||||
|
char* msg_auth_user_not_found; /*<<< "User not found in password database" */
|
||||||
|
char* msg_error_no_memory; /*<<< "No memory" */
|
||||||
|
char* msg_user_share_size_low; /*<<< "User is not sharing enough" */
|
||||||
|
char* msg_user_share_size_high; /*<<< "User is sharing too much" */
|
||||||
|
char* msg_user_slots_low; /*<<< "User have too few upload slots." */
|
||||||
|
char* msg_user_slots_high; /*<<< "User have too many upload slots." */
|
||||||
|
char* msg_user_hub_limit_low; /*<<< "User is on too few hubs." */
|
||||||
|
char* msg_user_hub_limit_high; /*<<< "User is on too many hubs." */
|
||||||
|
char* msg_user_flood_chat; /*<<< "Chat flood detected, messages are dropped." */
|
||||||
|
char* msg_user_flood_connect; /*<<< "Connect flood detected, connection refused." */
|
||||||
|
char* msg_user_flood_search; /*<<< "Search flood detected, search is stopped." */
|
||||||
|
char* msg_user_flood_update; /*<<< "Update flood detected." */
|
||||||
|
char* msg_user_flood_extras; /*<<< "Flood detected." */
|
||||||
|
char* msg_proto_no_common_hash; /*<<< "No common hash algorithm." */
|
||||||
|
char* msg_proto_obsolete_adc0; /*<<< "Client is using an obsolete ADC protocol version." */
|
||||||
|
};
|
||||||
|
|
||||||
349
src/core/hub.c
349
src/core/hub.c
@@ -21,6 +21,31 @@
|
|||||||
|
|
||||||
struct hub_info* g_hub = 0;
|
struct hub_info* g_hub = 0;
|
||||||
|
|
||||||
|
#define CHECK_CHAT_ONLY \
|
||||||
|
if (hub->config->chat_only && u->credentials < cred_operator) \
|
||||||
|
break
|
||||||
|
|
||||||
|
#define CHECK_FLOOD(TYPE, WARN) \
|
||||||
|
if (flood_control_check(&u->flood_ ## TYPE , hub->config->flood_ctl_ ## TYPE, hub->config->flood_ctl_interval, net_get_time())) \
|
||||||
|
{ \
|
||||||
|
if (WARN) \
|
||||||
|
{ \
|
||||||
|
hub_send_flood_warning(hub, u, hub->config->msg_user_flood_ ## TYPE); \
|
||||||
|
} \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ROUTE_MSG \
|
||||||
|
if (user_is_logged_in(u)) \
|
||||||
|
{ \
|
||||||
|
ret = route_message(hub, u, cmd); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
ret = -1; \
|
||||||
|
} \
|
||||||
|
break;
|
||||||
|
|
||||||
int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* line, size_t length)
|
int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* line, size_t length)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -36,20 +61,32 @@ int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* lin
|
|||||||
{
|
{
|
||||||
switch (cmd->cmd)
|
switch (cmd->cmd)
|
||||||
{
|
{
|
||||||
case ADC_CMD_HSUP: ret = hub_handle_support(hub, u, cmd); break;
|
case ADC_CMD_HSUP:
|
||||||
case ADC_CMD_HPAS: ret = hub_handle_password(hub, u, cmd); break;
|
CHECK_FLOOD(extras, 0);
|
||||||
case ADC_CMD_BINF: ret = hub_handle_info(hub, u, cmd); break;
|
ret = hub_handle_support(hub, u, cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CMD_HPAS:
|
||||||
|
CHECK_FLOOD(extras, 0);
|
||||||
|
ret = hub_handle_password(hub, u, cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CMD_BINF:
|
||||||
|
CHECK_FLOOD(update, 1);
|
||||||
|
ret = hub_handle_info(hub, u, cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
case ADC_CMD_DINF:
|
case ADC_CMD_DINF:
|
||||||
case ADC_CMD_EINF:
|
case ADC_CMD_EINF:
|
||||||
case ADC_CMD_FINF:
|
case ADC_CMD_FINF:
|
||||||
/* these must never be allowed for security reasons,
|
/* these must never be allowed for security reasons, so we ignore them. */
|
||||||
so we ignore them. */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ADC_CMD_EMSG:
|
case ADC_CMD_EMSG:
|
||||||
case ADC_CMD_DMSG:
|
case ADC_CMD_DMSG:
|
||||||
case ADC_CMD_BMSG:
|
case ADC_CMD_BMSG:
|
||||||
case ADC_CMD_FMSG:
|
case ADC_CMD_FMSG:
|
||||||
|
CHECK_FLOOD(chat, 1);
|
||||||
ret = hub_handle_chat_message(hub, u, cmd);
|
ret = hub_handle_chat_message(hub, u, cmd);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -57,26 +94,27 @@ int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* lin
|
|||||||
case ADC_CMD_DSCH:
|
case ADC_CMD_DSCH:
|
||||||
case ADC_CMD_ESCH:
|
case ADC_CMD_ESCH:
|
||||||
case ADC_CMD_FSCH:
|
case ADC_CMD_FSCH:
|
||||||
|
cmd->priority = -1;
|
||||||
|
CHECK_CHAT_ONLY;
|
||||||
|
CHECK_FLOOD(search, 1);
|
||||||
|
ROUTE_MSG;
|
||||||
|
|
||||||
case ADC_CMD_DRES:
|
case ADC_CMD_DRES:
|
||||||
|
cmd->priority = -1;
|
||||||
|
CHECK_CHAT_ONLY;
|
||||||
|
/* CHECK_FLOOD(search, 0); */
|
||||||
|
ROUTE_MSG;
|
||||||
|
|
||||||
case ADC_CMD_DRCM:
|
case ADC_CMD_DRCM:
|
||||||
case ADC_CMD_DCTM:
|
case ADC_CMD_DCTM:
|
||||||
cmd->priority = -1;
|
cmd->priority = -1;
|
||||||
if (hub->config->chat_only && u->credentials < cred_operator)
|
CHECK_CHAT_ONLY;
|
||||||
{
|
CHECK_FLOOD(connect, 1);
|
||||||
/* These below aren't allowed in chat only hubs */
|
ROUTE_MSG;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (user_is_logged_in(u))
|
CHECK_FLOOD(extras, 1);
|
||||||
{
|
ROUTE_MSG;
|
||||||
ret = route_message(hub, u, cmd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
adc_msg_free(cmd);
|
adc_msg_free(cmd);
|
||||||
}
|
}
|
||||||
@@ -137,17 +175,51 @@ int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_mess
|
|||||||
if (u->state == state_protocol)
|
if (u->state == state_protocol)
|
||||||
{
|
{
|
||||||
if (index == 0) ok = 0; /* Need to support *SOMETHING*, at least BASE */
|
if (index == 0) ok = 0; /* Need to support *SOMETHING*, at least BASE */
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
/* disconnect user. Do not send crap during initial handshake! */
|
||||||
|
hub_disconnect_user(hub, u, quit_logon_error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (ok)
|
if (user_flag_get(u, feature_base))
|
||||||
|
{
|
||||||
|
/* User supports ADC/1.0 and a hash we know */
|
||||||
|
if (user_flag_get(u, feature_tiger))
|
||||||
{
|
{
|
||||||
hub_send_handshake(hub, u);
|
hub_send_handshake(hub, u);
|
||||||
net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
|
net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* disconnect user. Do not send crap during initial handshake! */
|
// no common hash algorithm.
|
||||||
|
hub_send_status(hub, u, status_msg_proto_no_common_hash, status_level_fatal);
|
||||||
|
hub_disconnect_user(hub, u, quit_protocol_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (user_flag_get(u, feature_bas0))
|
||||||
|
{
|
||||||
|
if (hub->config->obsolete_clients)
|
||||||
|
{
|
||||||
|
hub_send_handshake(hub, u);
|
||||||
|
net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* disconnect user for using an obsolete client. */
|
||||||
|
char* tmp = adc_msg_escape(hub->config->msg_proto_obsolete_adc0);
|
||||||
|
struct adc_message* message = adc_msg_construct(ADC_CMD_IMSG, 6 + strlen(tmp));
|
||||||
|
adc_msg_add_argument(message, tmp);
|
||||||
|
hub_free(tmp);
|
||||||
|
route_to_user(hub, u, message);
|
||||||
|
adc_msg_free(message);
|
||||||
|
hub_disconnect_user(hub, u, quit_protocol_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Not speaking a compatible protocol - just disconnect. */
|
||||||
hub_disconnect_user(hub, u, quit_logon_error);
|
hub_disconnect_user(hub, u, quit_logon_error);
|
||||||
ret = -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,9 +257,15 @@ int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc
|
|||||||
int relay = 1;
|
int relay = 1;
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
if (!message || !user_is_logged_in(u))
|
if (!message)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (!user_is_logged_in(u))
|
||||||
|
{
|
||||||
|
hub_free(message);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ((cmd->cache[0] == 'B') && (message[0] == '!' || message[0] == '+'))
|
if ((cmd->cache[0] == 'B') && (message[0] == '!' || message[0] == '+'))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -393,6 +471,28 @@ void hub_send_password_challenge(struct hub_info* hub, struct hub_user* u)
|
|||||||
adc_msg_free(igpa);
|
adc_msg_free(igpa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hub_send_flood_warning(struct hub_info* hub, struct hub_user* u, const char* message)
|
||||||
|
{
|
||||||
|
struct adc_message* msg;
|
||||||
|
char* tmp;
|
||||||
|
|
||||||
|
if (user_flag_get(u, flag_flood))
|
||||||
|
return;
|
||||||
|
|
||||||
|
msg = adc_msg_construct(ADC_CMD_ISTA, 128);
|
||||||
|
if (msg)
|
||||||
|
{
|
||||||
|
tmp = adc_msg_escape(message);
|
||||||
|
adc_msg_add_argument(msg, "110");
|
||||||
|
adc_msg_add_argument(msg, tmp);
|
||||||
|
hub_free(tmp);
|
||||||
|
|
||||||
|
route_to_user(hub, u, msg);
|
||||||
|
user_flag_set(u, flag_flood);
|
||||||
|
adc_msg_free(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void hub_event_dispatcher(void* callback_data, struct event_data* message)
|
static void hub_event_dispatcher(void* callback_data, struct event_data* message)
|
||||||
{
|
{
|
||||||
struct hub_info* hub = (struct hub_info*) callback_data;
|
struct hub_info* hub = (struct hub_info*) callback_data;
|
||||||
@@ -552,7 +652,45 @@ static void server_alt_port_stop(struct hub_info* hub)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
static int load_ssl_certificates(struct hub_info* hub, struct hub_config* config)
|
||||||
|
{
|
||||||
|
if (config->tls_enable)
|
||||||
|
{
|
||||||
|
hub->ssl_method = SSLv23_method(); /* TLSv1_method() */
|
||||||
|
hub->ssl_ctx = SSL_CTX_new(hub->ssl_method);
|
||||||
|
|
||||||
|
/* Disable SSLv2 */
|
||||||
|
SSL_CTX_set_options(hub->ssl_ctx, SSL_OP_NO_SSLv2);
|
||||||
|
|
||||||
|
if (SSL_CTX_use_certificate_file(hub->ssl_ctx, config->tls_certificate, SSL_FILETYPE_PEM) < 0)
|
||||||
|
{
|
||||||
|
LOG_ERROR("SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SSL_CTX_use_PrivateKey_file(hub->ssl_ctx, config->tls_private_key, SSL_FILETYPE_PEM) < 0)
|
||||||
|
{
|
||||||
|
LOG_ERROR("SSL_CTX_use_PrivateKey_file: %s", ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SSL_CTX_check_private_key(hub->ssl_ctx) != 1)
|
||||||
|
{
|
||||||
|
LOG_FATAL("SSL_CTX_check_private_key: Private key does not match the certificate public key: %s", ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
LOG_INFO("Enabling TLS, using certificate: %s, private key: %s", config->tls_certificate, config->tls_private_key);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unload_ssl_certificates(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
if (hub->ssl_ctx)
|
||||||
|
{
|
||||||
|
SSL_CTX_free(hub->ssl_ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct hub_info* hub_start_service(struct hub_config* config)
|
struct hub_info* hub_start_service(struct hub_config* config)
|
||||||
{
|
{
|
||||||
@@ -583,31 +721,11 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
|||||||
LOG_INFO("Starting " PRODUCT "/" VERSION ", listening on %s:%d...", net_get_local_address(hub->server->sd), config->server_port);
|
LOG_INFO("Starting " PRODUCT "/" VERSION ", listening on %s:%d...", net_get_local_address(hub->server->sd), config->server_port);
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
if (config->tls_enable)
|
if (!load_ssl_certificates(hub, config))
|
||||||
{
|
{
|
||||||
hub->ssl_method = SSLv23_method(); /* TLSv1_method() */
|
hub_free(hub);
|
||||||
hub->ssl_ctx = SSL_CTX_new(hub->ssl_method);
|
|
||||||
|
|
||||||
/* Disable SSLv2 */
|
|
||||||
SSL_CTX_set_options(hub->ssl_ctx, SSL_OP_NO_SSLv2);
|
|
||||||
|
|
||||||
if (SSL_CTX_use_certificate_file(hub->ssl_ctx, config->tls_certificate, SSL_FILETYPE_PEM) < 0)
|
|
||||||
{
|
|
||||||
LOG_ERROR("SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(), NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SSL_CTX_use_PrivateKey_file(hub->ssl_ctx, config->tls_private_key, SSL_FILETYPE_PEM) < 0)
|
|
||||||
{
|
|
||||||
LOG_ERROR("SSL_CTX_use_PrivateKey_file: %s", ERR_error_string(ERR_get_error(), NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SSL_CTX_check_private_key(hub->ssl_ctx) != 1)
|
|
||||||
{
|
|
||||||
LOG_FATAL("SSL_CTX_check_private_key: Private key does not match the certificate public key: %s", ERR_error_string(ERR_get_error(), NULL));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
LOG_INFO("Enabling TLS, using certificate: %s, private key: %s", config->tls_certificate, config->tls_private_key);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
hub->config = config;
|
hub->config = config;
|
||||||
@@ -667,6 +785,10 @@ void hub_shutdown_service(struct hub_info* hub)
|
|||||||
{
|
{
|
||||||
LOG_DEBUG("hub_shutdown_service()");
|
LOG_DEBUG("hub_shutdown_service()");
|
||||||
|
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
unload_ssl_certificates(hub);
|
||||||
|
#endif
|
||||||
|
|
||||||
event_queue_shutdown(hub->queue);
|
event_queue_shutdown(hub->queue);
|
||||||
net_con_close(hub->server);
|
net_con_close(hub->server);
|
||||||
hub_free(hub->server);
|
hub_free(hub->server);
|
||||||
@@ -684,6 +806,45 @@ void hub_shutdown_service(struct hub_info* hub)
|
|||||||
g_hub = 0;
|
g_hub = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PLUGIN_SUPPORT
|
||||||
|
void hub_plugins_load(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
if (!hub->config->file_plugins || !*hub->config->file_plugins)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hub->plugins = hub_malloc_zero(sizeof(struct uhub_plugins));
|
||||||
|
if (!hub->plugins)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (plugin_initialize(hub->config, hub->plugins) < 0)
|
||||||
|
{
|
||||||
|
hub_free(hub->plugins);
|
||||||
|
hub->plugins = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hub_plugins_unload(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
if (!hub->plugins || !hub->plugins->loaded)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct uhub_plugin_handle* plugin = (struct uhub_plugin_handle*) list_get_first(hub->plugins->loaded);
|
||||||
|
while (plugin)
|
||||||
|
{
|
||||||
|
plugin_unload(plugin);
|
||||||
|
plugin = (struct uhub_plugin_handle*) list_get_next(hub->plugins->loaded);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_destroy(hub->plugins->loaded);
|
||||||
|
hub_free(hub->plugins->plugin_dir);
|
||||||
|
hub_free(hub->plugins);
|
||||||
|
hub->plugins = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
||||||
{
|
{
|
||||||
int fd, ret;
|
int fd, ret;
|
||||||
@@ -758,6 +919,10 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
|||||||
hub_free(tmp);
|
hub_free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PLUGIN_SUPPORT
|
||||||
|
hub_plugins_load(hub);
|
||||||
|
#endif
|
||||||
|
|
||||||
hub->status = (hub->config->hub_enabled ? hub_status_running : hub_status_disabled);
|
hub->status = (hub->config->hub_enabled ? hub_status_running : hub_status_disabled);
|
||||||
hub_free(server);
|
hub_free(server);
|
||||||
}
|
}
|
||||||
@@ -765,6 +930,10 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
|||||||
|
|
||||||
void hub_free_variables(struct hub_info* hub)
|
void hub_free_variables(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
|
#ifdef PLUGIN_SUPPORT
|
||||||
|
hub_plugins_unload(hub);
|
||||||
|
#endif
|
||||||
|
|
||||||
adc_msg_free(hub->command_info);
|
adc_msg_free(hub->command_info);
|
||||||
adc_msg_free(hub->command_banner);
|
adc_msg_free(hub->command_banner);
|
||||||
|
|
||||||
@@ -826,48 +995,56 @@ void hub_send_status(struct hub_info* hub, struct hub_user* user, enum status_me
|
|||||||
{
|
{
|
||||||
struct hub_config* cfg = hub->config;
|
struct hub_config* cfg = hub->config;
|
||||||
struct adc_message* cmd = adc_msg_construct(ADC_CMD_ISTA, 6);
|
struct adc_message* cmd = adc_msg_construct(ADC_CMD_ISTA, 6);
|
||||||
struct adc_message* qui = adc_msg_construct(ADC_CMD_IQUI, 256);
|
struct adc_message* qui = adc_msg_construct(ADC_CMD_IQUI, 512);
|
||||||
char code[4];
|
char code[4];
|
||||||
char buf[250];
|
char buf[256];
|
||||||
const char* text = 0;
|
const char* text = 0;
|
||||||
const char* flag = 0;
|
const char* flag = 0;
|
||||||
char* escaped_text = 0;
|
char* escaped_text = 0;
|
||||||
int reconnect_time = 0;
|
int reconnect_time = 0;
|
||||||
|
int redirect = 0;
|
||||||
|
|
||||||
if (!cmd) return;
|
if (!cmd || !qui)
|
||||||
|
{
|
||||||
|
adc_msg_free(cmd);
|
||||||
|
adc_msg_free(qui);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#define STATUS(CODE, MSG, FLAG, RCONTIME) case status_ ## MSG : set_status_code(level, CODE, code); text = cfg->MSG; flag = FLAG; reconnect_time = RCONTIME; break
|
#define STATUS(CODE, MSG, FLAG, RCONTIME, REDIRECT) case status_ ## MSG : set_status_code(level, CODE, code); text = cfg->MSG; flag = FLAG; reconnect_time = RCONTIME; redirect = REDIRECT; break
|
||||||
switch (msg)
|
switch (msg)
|
||||||
{
|
{
|
||||||
STATUS(11, msg_hub_full, 0, 600); /* FIXME: Proper timeout? */
|
STATUS(11, msg_hub_full, 0, 600, 1); /* FIXME: Proper timeout? */
|
||||||
STATUS(12, msg_hub_disabled, 0, -1);
|
STATUS(12, msg_hub_disabled, 0, -1, 1);
|
||||||
STATUS(26, msg_hub_registered_users_only, 0, 0);
|
STATUS(26, msg_hub_registered_users_only, 0, 0, 1);
|
||||||
STATUS(43, msg_inf_error_nick_missing, 0, 0);
|
STATUS(43, msg_inf_error_nick_missing, 0, 0, 0);
|
||||||
STATUS(43, msg_inf_error_nick_multiple, 0, 0);
|
STATUS(43, msg_inf_error_nick_multiple, 0, 0, 0);
|
||||||
STATUS(21, msg_inf_error_nick_invalid, 0, 0);
|
STATUS(21, msg_inf_error_nick_invalid, 0, 0, 0);
|
||||||
STATUS(21, msg_inf_error_nick_long, 0, 0);
|
STATUS(21, msg_inf_error_nick_long, 0, 0, 0);
|
||||||
STATUS(21, msg_inf_error_nick_short, 0, 0);
|
STATUS(21, msg_inf_error_nick_short, 0, 0, 0);
|
||||||
STATUS(21, msg_inf_error_nick_spaces, 0, 0);
|
STATUS(21, msg_inf_error_nick_spaces, 0, 0, 0);
|
||||||
STATUS(21, msg_inf_error_nick_bad_chars, 0, 0);
|
STATUS(21, msg_inf_error_nick_bad_chars, 0, 0, 0);
|
||||||
STATUS(21, msg_inf_error_nick_not_utf8, 0, 0);
|
STATUS(21, msg_inf_error_nick_not_utf8, 0, 0, 0);
|
||||||
STATUS(22, msg_inf_error_nick_taken, 0, 0);
|
STATUS(22, msg_inf_error_nick_taken, 0, 0, 0);
|
||||||
STATUS(21, msg_inf_error_nick_restricted, 0, 0);
|
STATUS(21, msg_inf_error_nick_restricted, 0, 0, 0);
|
||||||
STATUS(43, msg_inf_error_cid_invalid, "FBID", 0);
|
STATUS(43, msg_inf_error_cid_invalid, "FBID", 0, 0);
|
||||||
STATUS(43, msg_inf_error_cid_missing, "FMID", 0);
|
STATUS(43, msg_inf_error_cid_missing, "FMID", 0, 0);
|
||||||
STATUS(24, msg_inf_error_cid_taken, 0, 0);
|
STATUS(24, msg_inf_error_cid_taken, 0, 0, 0);
|
||||||
STATUS(43, msg_inf_error_pid_missing, "FMPD", 0);
|
STATUS(43, msg_inf_error_pid_missing, "FMPD", 0, 0);
|
||||||
STATUS(27, msg_inf_error_pid_invalid, "FBPD", 0);
|
STATUS(27, msg_inf_error_pid_invalid, "FBPD", 0, 0);
|
||||||
STATUS(31, msg_ban_permanently, 0, 0);
|
STATUS(31, msg_ban_permanently, 0, 0, 0);
|
||||||
STATUS(32, msg_ban_temporarily, "TL600", 600); /* FIXME: Proper timeout? */
|
STATUS(32, msg_ban_temporarily, "TL600", 600, 0); /* FIXME: Proper timeout? */
|
||||||
STATUS(23, msg_auth_invalid_password, 0, 0);
|
STATUS(23, msg_auth_invalid_password, 0, 0, 0);
|
||||||
STATUS(20, msg_auth_user_not_found, 0, 0);
|
STATUS(20, msg_auth_user_not_found, 0, 0, 0);
|
||||||
STATUS(30, msg_error_no_memory, 0, 0);
|
STATUS(30, msg_error_no_memory, 0, 0, 0);
|
||||||
STATUS(43, msg_user_share_size_low, "FB" ADC_INF_FLAG_SHARED_SIZE, 0);
|
STATUS(43, msg_user_share_size_low, "FB" ADC_INF_FLAG_SHARED_SIZE, 0, 1);
|
||||||
STATUS(43, msg_user_share_size_high, "FB" ADC_INF_FLAG_SHARED_SIZE, 0);
|
STATUS(43, msg_user_share_size_high, "FB" ADC_INF_FLAG_SHARED_SIZE, 0, 1);
|
||||||
STATUS(43, msg_user_slots_low, "FB" ADC_INF_FLAG_UPLOAD_SLOTS, 0);
|
STATUS(43, msg_user_slots_low, "FB" ADC_INF_FLAG_UPLOAD_SLOTS, 0, 1);
|
||||||
STATUS(43, msg_user_slots_high, "FB" ADC_INF_FLAG_UPLOAD_SLOTS, 0);
|
STATUS(43, msg_user_slots_high, "FB" ADC_INF_FLAG_UPLOAD_SLOTS, 0, 1);
|
||||||
STATUS(43, msg_user_hub_limit_low, 0, 0);
|
STATUS(43, msg_user_hub_limit_low, 0, 0, 1);
|
||||||
STATUS(43, msg_user_hub_limit_high, 0, 0);
|
STATUS(43, msg_user_hub_limit_high, 0, 0, 1);
|
||||||
|
STATUS(47, msg_proto_no_common_hash, 0, -1, 1);
|
||||||
|
STATUS(40, msg_proto_obsolete_adc0, 0, -1, 1);
|
||||||
}
|
}
|
||||||
#undef STATUS
|
#undef STATUS
|
||||||
|
|
||||||
@@ -886,14 +1063,20 @@ void hub_send_status(struct hub_info* hub, struct hub_user* user, enum status_me
|
|||||||
if (level >= status_level_fatal)
|
if (level >= status_level_fatal)
|
||||||
{
|
{
|
||||||
snprintf(buf, 230, "MS%s", escaped_text);
|
snprintf(buf, 230, "MS%s", escaped_text);
|
||||||
adc_msg_add_argument(cmd, buf);
|
adc_msg_add_argument(qui, buf);
|
||||||
|
|
||||||
if (reconnect_time != 0)
|
if (reconnect_time != 0)
|
||||||
{
|
{
|
||||||
snprintf(buf, 10, "TL%d", reconnect_time);
|
snprintf(buf, 10, "TL%d", reconnect_time);
|
||||||
adc_msg_add_argument(cmd, buf);
|
adc_msg_add_argument(qui, buf);
|
||||||
}
|
}
|
||||||
route_to_user(hub, user, cmd);
|
|
||||||
|
if (redirect && *hub->config->redirect_addr)
|
||||||
|
{
|
||||||
|
snprintf(buf, 255, "RD%s", hub->config->redirect_addr);
|
||||||
|
adc_msg_add_argument(qui, buf);
|
||||||
|
}
|
||||||
|
route_to_user(hub, user, qui);
|
||||||
}
|
}
|
||||||
|
|
||||||
hub_free(escaped_text);
|
hub_free(escaped_text);
|
||||||
@@ -936,6 +1119,8 @@ const char* hub_get_status_message(struct hub_info* hub, enum status_message msg
|
|||||||
STATUS(msg_user_slots_high);
|
STATUS(msg_user_slots_high);
|
||||||
STATUS(msg_user_hub_limit_low);
|
STATUS(msg_user_hub_limit_low);
|
||||||
STATUS(msg_user_hub_limit_high);
|
STATUS(msg_user_hub_limit_high);
|
||||||
|
STATUS(msg_proto_no_common_hash);
|
||||||
|
STATUS(msg_proto_obsolete_adc0);
|
||||||
}
|
}
|
||||||
#undef STATUS
|
#undef STATUS
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
@@ -975,6 +1160,8 @@ const char* hub_get_status_message_log(struct hub_info* hub, enum status_message
|
|||||||
STATUS(msg_user_slots_high);
|
STATUS(msg_user_slots_high);
|
||||||
STATUS(msg_user_hub_limit_low);
|
STATUS(msg_user_hub_limit_low);
|
||||||
STATUS(msg_user_hub_limit_high);
|
STATUS(msg_user_hub_limit_high);
|
||||||
|
STATUS(msg_proto_no_common_hash);
|
||||||
|
STATUS(msg_proto_obsolete_adc0);
|
||||||
}
|
}
|
||||||
#undef STATUS
|
#undef STATUS
|
||||||
return "unknown";
|
return "unknown";
|
||||||
|
|||||||
@@ -53,6 +53,10 @@ enum status_message
|
|||||||
status_msg_user_hub_limit_low = -44, /* Use is on too few hubs. */
|
status_msg_user_hub_limit_low = -44, /* Use is on too few hubs. */
|
||||||
status_msg_user_hub_limit_high = -45, /* Use is on too many hubs. */
|
status_msg_user_hub_limit_high = -45, /* Use is on too many hubs. */
|
||||||
|
|
||||||
|
status_msg_proto_no_common_hash = -50, /* No common hash algorithms */
|
||||||
|
status_msg_proto_obsolete_adc0 = -51, /* Client is using an obsolete protocol version */
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -110,6 +114,10 @@ struct hub_info
|
|||||||
struct linked_list* chat_history; /* Chat history */
|
struct linked_list* chat_history; /* Chat history */
|
||||||
struct linked_list* logout_info; /* Log of people logging out. */
|
struct linked_list* logout_info; /* Log of people logging out. */
|
||||||
|
|
||||||
|
#ifdef PLUGIN_SUPPORT
|
||||||
|
struct uhub_plugins* plugins;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
SSL_METHOD* ssl_method;
|
SSL_METHOD* ssl_method;
|
||||||
SSL_CTX* ssl_ctx;
|
SSL_CTX* ssl_ctx;
|
||||||
@@ -223,6 +231,11 @@ extern void hub_send_password_challenge(struct hub_info* hub, struct hub_user* u
|
|||||||
*/
|
*/
|
||||||
extern void hub_send_status(struct hub_info*, struct hub_user* user, enum status_message msg, enum msg_status_level level);
|
extern void hub_send_status(struct hub_info*, struct hub_user* user, enum status_message msg, enum msg_status_level level);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warn user about flooding.
|
||||||
|
*/
|
||||||
|
extern void hub_send_flood_warning(struct hub_info*, struct hub_user* user, const char* message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates memory, initializes the hub based on the configuration,
|
* Allocates memory, initializes the hub based on the configuration,
|
||||||
* and returns a hub handle.
|
* and returns a hub handle.
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
static void log_user_login(struct hub_user* u)
|
static void log_user_login(struct hub_user* u)
|
||||||
{
|
{
|
||||||
@@ -67,6 +68,10 @@ void on_login_success(struct hub_info* hub, struct hub_user* u)
|
|||||||
/* Print log message */
|
/* Print log message */
|
||||||
log_user_login(u);
|
log_user_login(u);
|
||||||
|
|
||||||
|
#ifdef PLUGIN_SUPPORT
|
||||||
|
plugin_log_user_login_success(hub, u);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* 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))
|
||||||
route_info_message(hub, u);
|
route_info_message(hub, u);
|
||||||
@@ -109,6 +114,11 @@ void on_logout_user(struct hub_info* hub, struct hub_user* user)
|
|||||||
{
|
{
|
||||||
const char* reason = user_get_quit_reason_string(user->quit_reason);
|
const char* reason = user_get_quit_reason_string(user->quit_reason);
|
||||||
log_user_logout(user, reason);
|
log_user_logout(user, reason);
|
||||||
|
|
||||||
|
#ifdef PLUGIN_SUPPORT
|
||||||
|
plugin_log_user_logout(hub, user);
|
||||||
|
#endif
|
||||||
|
|
||||||
hub_logout_log(hub, user);
|
hub_logout_log(hub, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ void hub_sendq_add(struct hub_sendq* q, struct adc_message* msg_)
|
|||||||
#ifdef DEBUG_SENDQ
|
#ifdef DEBUG_SENDQ
|
||||||
debug_msg("hub_sendq_add", msg);
|
debug_msg("hub_sendq_add", msg);
|
||||||
#endif
|
#endif
|
||||||
|
assert(msg->cache && *msg->cache);
|
||||||
list_append(q->queue, msg);
|
list_append(q->queue, msg);
|
||||||
q->size += msg->length;
|
q->size += msg->length;
|
||||||
}
|
}
|
||||||
@@ -146,7 +147,7 @@ int hub_sendq_send(struct hub_sendq* q, struct hub_user* user)
|
|||||||
int ret;
|
int ret;
|
||||||
struct adc_message* msg = list_get_first(q->queue);
|
struct adc_message* msg = list_get_first(q->queue);
|
||||||
if (!msg) return 0;
|
if (!msg) return 0;
|
||||||
|
assert(msg->cache && *msg->cache);
|
||||||
ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
|
ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
|
||||||
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -674,7 +674,6 @@ int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct ad
|
|||||||
/* Private ID must never be broadcasted - drop it! */
|
/* Private ID must never be broadcasted - drop it! */
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
|
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
|
||||||
|
|
||||||
|
|
||||||
code = set_credentials(hub, user, cmd);
|
code = set_credentials(hub, user, cmd);
|
||||||
|
|
||||||
/* Note: this must be done *after* set_credentials. */
|
/* Note: this must be done *after* set_credentials. */
|
||||||
@@ -798,3 +797,5 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -24,41 +24,16 @@
|
|||||||
/* FIXME: This should not be needed! */
|
/* FIXME: This should not be needed! */
|
||||||
extern struct hub_info* g_hub;
|
extern struct hub_info* g_hub;
|
||||||
|
|
||||||
#ifdef DEBUG_SENDQ
|
|
||||||
void debug_sendq_send(struct hub_user* user, int sent, int total)
|
|
||||||
{
|
|
||||||
LOG_DUMP("SEND: sd=%d, %d/%d bytes\n", user->connection->sd, sent, total);
|
|
||||||
if (sent == -1)
|
|
||||||
{
|
|
||||||
int err = net_error();
|
|
||||||
LOG_DUMP(" errno: %d - %s\n", err, net_error_string(err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void debug_sendq_recv(struct hub_user* user, int received, int max, const char* buffer)
|
|
||||||
{
|
|
||||||
LOG_DUMP("RECV: %d/%d bytes\n", received, (int) max);
|
|
||||||
if (received == -1)
|
|
||||||
{
|
|
||||||
int err = net_error();
|
|
||||||
LOG_DUMP(" errno: %d - %s\n", err, net_error_string(err));
|
|
||||||
}
|
|
||||||
else if (received > 0)
|
|
||||||
{
|
|
||||||
char* data = hub_malloc_zero(received + 1);
|
|
||||||
memcpy(data, buffer, received);
|
|
||||||
LOG_DUMP("RECV: \"%s\"\n", data);
|
|
||||||
hub_free(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int handle_net_read(struct hub_user* user)
|
int handle_net_read(struct hub_user* user)
|
||||||
{
|
{
|
||||||
static char buf[MAX_RECV_BUF];
|
static char buf[MAX_RECV_BUF];
|
||||||
struct hub_recvq* q = user->recv_queue;
|
struct hub_recvq* q = user->recv_queue;
|
||||||
size_t buf_size = hub_recvq_get(q, buf, MAX_RECV_BUF);
|
size_t buf_size = hub_recvq_get(q, buf, MAX_RECV_BUF);
|
||||||
ssize_t size = net_con_recv(user->connection, buf, MAX_RECV_BUF);
|
ssize_t size;
|
||||||
|
|
||||||
|
if (user_flag_get(user, flag_maxbuf))
|
||||||
|
buf_size = 0;
|
||||||
|
size = net_con_recv(user->connection, buf + buf_size, MAX_RECV_BUF - buf_size);
|
||||||
|
|
||||||
if (size > 0)
|
if (size > 0)
|
||||||
buf_size += size;
|
buf_size += size;
|
||||||
@@ -200,8 +175,10 @@ void net_on_accept(struct net_connection* con, int event, void *arg)
|
|||||||
struct hub_info* hub = (struct hub_info*) arg;
|
struct hub_info* hub = (struct hub_info*) arg;
|
||||||
struct hub_probe* probe = 0;
|
struct hub_probe* probe = 0;
|
||||||
struct ip_addr_encap ipaddr;
|
struct ip_addr_encap ipaddr;
|
||||||
const char* addr;
|
|
||||||
int server_fd = net_con_get_sd(con);
|
int server_fd = net_con_get_sd(con);
|
||||||
|
#ifdef PLUGIN_SUPPORT
|
||||||
|
plugin_st status;
|
||||||
|
#endif
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@@ -219,24 +196,23 @@ void net_on_accept(struct net_connection* con, int event, void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = ip_convert_to_string(&ipaddr);
|
#ifdef PLUGIN_SUPPORT
|
||||||
|
status = plugin_check_ip_early(hub, &ipaddr);
|
||||||
/* FIXME: Should have a plugin log this */
|
if (status == st_deny)
|
||||||
LOG_TRACE("Got connection from %s", addr);
|
|
||||||
|
|
||||||
/* FIXME: A plugin should perform this check: is IP banned? */
|
|
||||||
if (acl_is_ip_banned(hub->acl, addr))
|
|
||||||
{
|
{
|
||||||
LOG_INFO("Denied [%s] (IP banned)", addr);
|
plugin_log_connection_denied(hub, &ipaddr);
|
||||||
net_con_close(con);
|
net_close(fd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugin_log_connection_accepted(hub, &ipaddr);
|
||||||
|
#endif
|
||||||
|
|
||||||
probe = probe_create(hub, fd, &ipaddr);
|
probe = probe_create(hub, fd, &ipaddr);
|
||||||
if (!probe)
|
if (!probe)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Unable to create probe after socket accepted. Out of memory?");
|
LOG_ERROR("Unable to create probe after socket accepted. Out of memory?");
|
||||||
net_con_close(con);
|
net_close(fd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
89
src/core/plugininvoke.c
Normal file
89
src/core/plugininvoke.c
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
|
#define PLUGIN_INVOKE(HUB, FUNCNAME, CODE) \
|
||||||
|
if (HUB->plugins && HUB->plugins->loaded) \
|
||||||
|
{ \
|
||||||
|
struct uhub_plugin_handle* plugin = (struct uhub_plugin_handle*) list_get_first(HUB->plugins->loaded); \
|
||||||
|
while (plugin) \
|
||||||
|
{ \
|
||||||
|
if (plugin->funcs.FUNCNAME) \
|
||||||
|
CODE \
|
||||||
|
plugin = (struct uhub_plugin_handle*) list_get_next(HUB->plugins->loaded); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr)
|
||||||
|
{
|
||||||
|
plugin_st status = st_default;
|
||||||
|
PLUGIN_INVOKE(hub, login_check_ip_early, {
|
||||||
|
status = plugin->funcs.login_check_ip_early(addr);
|
||||||
|
if (status != st_default)
|
||||||
|
break;
|
||||||
|
});
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_check_ip_late(struct hub_info* hub, struct ip_addr_encap* addr)
|
||||||
|
{
|
||||||
|
plugin_st status = st_default;
|
||||||
|
PLUGIN_INVOKE(hub, login_check_ip_late, {
|
||||||
|
status = plugin->funcs.login_check_ip_late(addr);
|
||||||
|
if (status != st_default)
|
||||||
|
break;
|
||||||
|
});
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* ipaddr)
|
||||||
|
{
|
||||||
|
const char* addr = ip_convert_to_string(ipaddr);
|
||||||
|
LOG_TRACE("Got connection from %s", addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_log_connection_denied(struct hub_info* hub, struct ip_addr_encap* ipaddr)
|
||||||
|
{
|
||||||
|
const char* addr = ip_convert_to_string(ipaddr);
|
||||||
|
LOG_INFO("Denied connection from %s", addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_log_user_login_success(struct hub_info* hub, struct hub_user* user)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_log_user_login_error(struct hub_info* hub, struct hub_user* user)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_log_user_logout(struct hub_info* hub, struct hub_user* user)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void convert_user_to_plugin_user(struct plugin_user* puser, struct hub_user* user)
|
||||||
|
{
|
||||||
|
puser->sid = user->id.sid;
|
||||||
|
puser->nick = user->id.nick;
|
||||||
|
puser->cid = user->id.cid;
|
||||||
|
puser->addr = user->id.addr;
|
||||||
|
}
|
||||||
46
src/core/plugininvoke.h
Normal file
46
src/core/plugininvoke.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_UHUB_PLUGIN_INVOKE_H
|
||||||
|
#define HAVE_UHUB_PLUGIN_INVOKE_H
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
|
#ifdef PLUGIN_SUPPORT
|
||||||
|
|
||||||
|
struct hub_info;
|
||||||
|
struct ip_addr_encap;
|
||||||
|
|
||||||
|
void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* addr);
|
||||||
|
void plugin_log_connection_denied(struct hub_info* hub, struct ip_addr_encap* addr);
|
||||||
|
void plugin_log_user_login_success(struct hub_info* hub, struct hub_user* user);
|
||||||
|
void plugin_log_user_login_error(struct hub_info* hub, struct hub_user* user);
|
||||||
|
void plugin_log_user_logout(struct hub_info* hub, struct hub_user* user);
|
||||||
|
|
||||||
|
plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr);
|
||||||
|
plugin_st plugin_check_ip_late(struct hub_info* hub, struct ip_addr_encap* addr);
|
||||||
|
|
||||||
|
plugin_st plugin_check_nickname_valid(struct hub_info* hub, const char* nick);
|
||||||
|
plugin_st plugin_check_nickname_reserved(struct hub_info* hub, const char* nick);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // HAVE_UHUB_PLUGIN_INVOKE_H
|
||||||
187
src/core/pluginloader.c
Normal file
187
src/core/pluginloader.c
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
#ifdef PLUGIN_SUPPORT
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
|
struct uhub_plugin* plugin_open(const char* filename)
|
||||||
|
{
|
||||||
|
LOG_TRACE("plugin_open: \"%s\"", filename);
|
||||||
|
#ifdef HAVE_DLOPEN
|
||||||
|
struct uhub_plugin* plugin = (struct uhub_plugin*) hub_malloc_zero(sizeof(struct uhub_plugin));
|
||||||
|
if (!plugin)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin->handle = dlopen(filename, RTLD_LAZY);
|
||||||
|
|
||||||
|
if (!plugin->handle)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Unable to open plugin %s: %s", filename, dlerror());
|
||||||
|
hub_free(plugin);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_close(struct uhub_plugin* plugin)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_DLOPEN
|
||||||
|
dlclose(plugin->handle);
|
||||||
|
hub_free(plugin);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void* plugin_lookup_symbol(struct uhub_plugin* plugin, const char* symbol)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_DLOPEN
|
||||||
|
void* addr = dlsym(plugin->handle, symbol);
|
||||||
|
return addr;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
struct uhub_plugin_handle* plugin_load(const char* filename, const char* config)
|
||||||
|
{
|
||||||
|
plugin_register_f register_f;
|
||||||
|
plugin_unregister_f unregister_f;
|
||||||
|
int ret;
|
||||||
|
struct uhub_plugin_handle* handle = hub_malloc_zero(sizeof(struct uhub_plugin_handle));
|
||||||
|
struct uhub_plugin* plugin = plugin_open(filename);
|
||||||
|
|
||||||
|
if (!plugin)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
|
{
|
||||||
|
plugin_close(plugin);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->handle = plugin;
|
||||||
|
register_f = plugin_lookup_symbol(plugin, "plugin_register");
|
||||||
|
unregister_f = plugin_lookup_symbol(plugin, "plugin_unregister");
|
||||||
|
|
||||||
|
if (register_f && unregister_f)
|
||||||
|
{
|
||||||
|
ret = register_f(handle, config);
|
||||||
|
if (ret == 0)
|
||||||
|
{
|
||||||
|
if (handle->plugin_api_version == PLUGIN_API_VERSION && handle->plugin_funcs_size == sizeof(struct plugin_funcs))
|
||||||
|
{
|
||||||
|
LOG_INFO("Loaded plugin: %s: %s, version %s.", filename, handle->name, handle->version);
|
||||||
|
LOG_TRACE("Plugin API version: %d (func table size: " PRINTF_SIZE_T ")", handle->plugin_api_version, handle->plugin_funcs_size);
|
||||||
|
plugin->unregister = unregister_f;
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR("Unable to load plugin: %s - API version mistmatch", filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR("Unable to load plugin: %s - Failed to initialize", filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_close(plugin);
|
||||||
|
hub_free(handle);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_unload(struct uhub_plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
plugin->handle->unregister(plugin);
|
||||||
|
plugin_close(plugin->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int plugin_parse_line(char* line, int line_count, void* ptr_data)
|
||||||
|
{
|
||||||
|
struct uhub_plugins* handle = (struct uhub_plugins*) ptr_data;
|
||||||
|
char* pos;
|
||||||
|
|
||||||
|
strip_off_ini_line_comments(line, line_count);
|
||||||
|
|
||||||
|
line = strip_white_space(line);
|
||||||
|
if (!*line)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
LOG_TRACE("plugin: parse line %d: \"%s\"", line_count, line);
|
||||||
|
|
||||||
|
// Set plugin directory.
|
||||||
|
pos = strstr(line, "plugin_directory");
|
||||||
|
if (pos && is_white_space(line[(pos - line) + strlen("plugin_directory")]))
|
||||||
|
{
|
||||||
|
if (handle->plugin_dir)
|
||||||
|
hub_free(handle->plugin_dir);
|
||||||
|
handle->plugin_dir = strdup(strip_white_space(pos + strlen("plugin_directory") + 1));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load plugin
|
||||||
|
pos = strstr(line, "plugin");
|
||||||
|
if (pos && is_white_space(line[(pos - line) + strlen("plugin")]))
|
||||||
|
{
|
||||||
|
char* data = strip_white_space(pos + strlen("plugin") + 1);
|
||||||
|
if (*data)
|
||||||
|
{
|
||||||
|
LOG_TRACE("Load plugin: \"%s\"", data);
|
||||||
|
struct uhub_plugin_handle* plugin = plugin_load(data, "");
|
||||||
|
if (plugin)
|
||||||
|
{
|
||||||
|
list_append(handle->loaded, plugin);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_initialize(struct hub_config* config, struct uhub_plugins* handle)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
handle->loaded = list_create();
|
||||||
|
if (!handle->loaded)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (config)
|
||||||
|
{
|
||||||
|
if (!*config->file_plugins)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = file_read_lines(config->file_plugins, handle, &plugin_parse_line);
|
||||||
|
if (ret == -1)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* PLUGIN_SUPPORT */
|
||||||
62
src/core/pluginloader.h
Normal file
62
src/core/pluginloader.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_UHUB_PLUGIN_LOADER_H
|
||||||
|
#define HAVE_UHUB_PLUGIN_LOADER_H
|
||||||
|
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
|
#ifdef PLUGIN_SUPPORT
|
||||||
|
|
||||||
|
struct hub_config;
|
||||||
|
struct linked_list;
|
||||||
|
struct uhub_plugin_handle;
|
||||||
|
|
||||||
|
struct uhub_plugin
|
||||||
|
{
|
||||||
|
#ifdef HAVE_DLOPEN
|
||||||
|
void* handle;
|
||||||
|
#endif
|
||||||
|
plugin_unregister_f unregister;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct uhub_plugins
|
||||||
|
{
|
||||||
|
struct linked_list* loaded;
|
||||||
|
char* plugin_dir;
|
||||||
|
};
|
||||||
|
|
||||||
|
// High level plugin loader ode
|
||||||
|
extern struct uhub_plugin_handle* plugin_load(const char* filename, const char* config);
|
||||||
|
extern void plugin_unload(struct uhub_plugin_handle* plugin);
|
||||||
|
|
||||||
|
// extern void plugin_unload(struct uhub_plugin_handle*);
|
||||||
|
extern int plugin_initialize(struct hub_config* config, struct uhub_plugins* handle);
|
||||||
|
|
||||||
|
// Low level plugin loader code (used internally)
|
||||||
|
extern struct uhub_plugin* plugin_open(const char* filename);
|
||||||
|
extern void plugin_close(struct uhub_plugin*);
|
||||||
|
extern void* plugin_lookup_symbol(struct uhub_plugin*, const char* symbol);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* PLUGIN_SUPPORT */
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_PLUGIN_LOADER_H */
|
||||||
|
|
||||||
@@ -46,6 +46,13 @@ static void probe_net_event(struct net_connection* con, int events, void *arg)
|
|||||||
if (memcmp(probe_recvbuf, "HSUP", 4) == 0)
|
if (memcmp(probe_recvbuf, "HSUP", 4) == 0)
|
||||||
{
|
{
|
||||||
LOG_TRACE("Probed ADC");
|
LOG_TRACE("Probed ADC");
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
if (probe->hub->config->tls_enable && probe->hub->config->tls_require)
|
||||||
|
{
|
||||||
|
LOG_TRACE("Not TLS connection - closing connection.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if (user_create(probe->hub, probe->connection, &probe->addr))
|
if (user_create(probe->hub, probe->connection, &probe->addr))
|
||||||
{
|
{
|
||||||
probe->connection = 0;
|
probe->connection = 0;
|
||||||
@@ -85,9 +92,10 @@ static void probe_net_event(struct net_connection* con, int events, void *arg)
|
|||||||
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx);
|
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#else
|
||||||
probe_destroy(probe);
|
probe_destroy(probe);
|
||||||
return;
|
return;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,6 +106,8 @@ int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_messag
|
|||||||
if (!user->connection)
|
if (!user->connection)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
assert(msg->cache && *msg->cache);
|
||||||
|
|
||||||
if (hub_sendq_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline))
|
if (hub_sendq_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline))
|
||||||
{
|
{
|
||||||
/* Perform oportunistic write */
|
/* Perform oportunistic write */
|
||||||
|
|||||||
@@ -54,6 +54,12 @@ struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, s
|
|||||||
|
|
||||||
memcpy(&user->id.addr, addr, sizeof(struct ip_addr_encap));
|
memcpy(&user->id.addr, addr, sizeof(struct ip_addr_encap));
|
||||||
user_set_state(user, state_protocol);
|
user_set_state(user, state_protocol);
|
||||||
|
|
||||||
|
flood_control_reset(&user->flood_chat);
|
||||||
|
flood_control_reset(&user->flood_connect);
|
||||||
|
flood_control_reset(&user->flood_search);
|
||||||
|
flood_control_reset(&user->flood_update);
|
||||||
|
flood_control_reset(&user->flood_extras);
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,8 +89,15 @@ void user_set_state(struct hub_user* user, enum user_state state)
|
|||||||
void user_set_info(struct hub_user* user, struct adc_message* cmd)
|
void user_set_info(struct hub_user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
adc_msg_free(user->info);
|
adc_msg_free(user->info);
|
||||||
|
if (cmd)
|
||||||
|
{
|
||||||
user->info = adc_msg_incref(cmd);
|
user->info = adc_msg_incref(cmd);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
user->info = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void user_update_info(struct hub_user* u, struct adc_message* cmd)
|
void user_update_info(struct hub_user* u, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
@@ -127,10 +140,9 @@ static int convert_support_fourcc(int fourcc)
|
|||||||
{
|
{
|
||||||
switch (fourcc)
|
switch (fourcc)
|
||||||
{
|
{
|
||||||
case FOURCC('B','A','S','0'): /* Obsolete */
|
case FOURCC('B','A','S','0'):
|
||||||
#ifndef OLD_ADC_SUPPORT
|
return feature_bas0;
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
case FOURCC('B','A','S','E'):
|
case FOURCC('B','A','S','E'):
|
||||||
return feature_base;
|
return feature_base;
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
struct hub_info;
|
struct hub_info;
|
||||||
struct hub_iobuf;
|
struct hub_iobuf;
|
||||||
|
struct flood_control;
|
||||||
|
|
||||||
enum user_state
|
enum user_state
|
||||||
{
|
{
|
||||||
@@ -45,6 +46,8 @@ enum user_flags
|
|||||||
feature_ping = 0x00000080, /** PING: Hub pinger information extension */
|
feature_ping = 0x00000080, /** PING: Hub pinger information extension */
|
||||||
feature_link = 0x00000100, /** LINK: Hub link (not supported) */
|
feature_link = 0x00000100, /** LINK: Hub link (not supported) */
|
||||||
feature_adcs = 0x00000200, /** ADCS: ADC over TLS/SSL */
|
feature_adcs = 0x00000200, /** ADCS: ADC over TLS/SSL */
|
||||||
|
feature_bas0 = 0x00000400, /** BAS0: Obsolete pre-ADC/1.0 protocol version */
|
||||||
|
flag_flood = 0x00400000, /** User has been notified about flooding. */
|
||||||
flag_muted = 0x00800000, /** User is muted (cannot chat) */
|
flag_muted = 0x00800000, /** User is muted (cannot chat) */
|
||||||
flag_ignore = 0x01000000, /** Ignore further reads */
|
flag_ignore = 0x01000000, /** Ignore further reads */
|
||||||
flag_maxbuf = 0x02000000, /** Hit max buf read, ignore msg */
|
flag_maxbuf = 0x02000000, /** Hit max buf read, ignore msg */
|
||||||
@@ -116,6 +119,11 @@ struct hub_user
|
|||||||
struct hub_user_limits limits; /** Data used for limitation */
|
struct hub_user_limits limits; /** Data used for limitation */
|
||||||
enum user_quit_reason quit_reason; /** Quit reason (see user_quit_reason) */
|
enum user_quit_reason quit_reason; /** Quit reason (see user_quit_reason) */
|
||||||
|
|
||||||
|
struct flood_control flood_chat;
|
||||||
|
struct flood_control flood_connect;
|
||||||
|
struct flood_control flood_search;
|
||||||
|
struct flood_control flood_update;
|
||||||
|
struct flood_control flood_extras;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -248,7 +248,6 @@ int uman_send_user_list(struct hub_info* hub, struct hub_user* target)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void uman_send_quit_message(struct hub_info* hub, struct hub_user* leaving)
|
void uman_send_quit_message(struct hub_info* hub, struct hub_user* leaving)
|
||||||
{
|
{
|
||||||
struct adc_message* command = adc_msg_construct(ADC_CMD_IQUI, 6);
|
struct adc_message* command = adc_msg_construct(ADC_CMD_IQUI, 6);
|
||||||
@@ -262,7 +261,6 @@ void uman_send_quit_message(struct hub_info* hub, struct hub_user* leaving)
|
|||||||
adc_msg_free(command);
|
adc_msg_free(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sid_t uman_get_free_sid(struct hub_info* hub, struct hub_user* user)
|
sid_t uman_get_free_sid(struct hub_info* hub, struct hub_user* user)
|
||||||
{
|
{
|
||||||
sid_t sid = sid_alloc(hub->users->sids, user);
|
sid_t sid = sid_alloc(hub->users->sids, user);
|
||||||
|
|||||||
@@ -76,14 +76,11 @@ int net_backend_init()
|
|||||||
g_backend->common.num = 0;
|
g_backend->common.num = 0;
|
||||||
g_backend->common.max = net_get_max_sockets();
|
g_backend->common.max = net_get_max_sockets();
|
||||||
g_backend->now = time(0);
|
g_backend->now = time(0);
|
||||||
timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 600); /* FIXME: max 600 secs! */
|
timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 120); /* FIXME: max 120 secs! */
|
||||||
g_backend->cleaner = net_cleanup_initialize(g_backend->common.max);
|
g_backend->cleaner = net_cleanup_initialize(g_backend->common.max);
|
||||||
|
|
||||||
for (n = 0; n < sizeof(net_backend_init_funcs); n++)
|
for (n = 0; net_backend_init_funcs[n]; n++)
|
||||||
{
|
{
|
||||||
if (!net_backend_init_funcs[n])
|
|
||||||
break;
|
|
||||||
|
|
||||||
g_backend->data = net_backend_init_funcs[n](&g_backend->handler, &g_backend->common);
|
g_backend->data = net_backend_init_funcs[n](&g_backend->handler, &g_backend->common);
|
||||||
if (g_backend->data)
|
if (g_backend->data)
|
||||||
{
|
{
|
||||||
@@ -155,6 +152,12 @@ int net_backend_process()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_t net_get_time()
|
||||||
|
{
|
||||||
|
return g_backend->now;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events)
|
void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events)
|
||||||
{
|
{
|
||||||
g_backend->handler.con_init(g_backend->data, con, sd, callback, ptr);
|
g_backend->handler.con_init(g_backend->data, con, sd, callback, ptr);
|
||||||
|
|||||||
@@ -75,6 +75,11 @@ extern void net_backend_shutdown();
|
|||||||
*/
|
*/
|
||||||
extern int net_backend_process();
|
extern int net_backend_process();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current time.
|
||||||
|
*/
|
||||||
|
time_t net_get_time();
|
||||||
|
|
||||||
extern struct timeout_queue* net_backend_get_timeout_queue();
|
extern struct timeout_queue* net_backend_get_timeout_queue();
|
||||||
|
|
||||||
struct net_cleanup_handler* net_cleanup_initialize(size_t max);
|
struct net_cleanup_handler* net_cleanup_initialize(size_t max);
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ struct net_backend* net_backend_init_epoll(struct net_backend_handler* handler,
|
|||||||
if (backend->epfd == -1)
|
if (backend->epfd == -1)
|
||||||
{
|
{
|
||||||
LOG_WARN("Unable to create epoll socket.");
|
LOG_WARN("Unable to create epoll socket.");
|
||||||
|
hub_free(backend);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,20 +30,31 @@
|
|||||||
struct net_connection_kqueue
|
struct net_connection_kqueue
|
||||||
{
|
{
|
||||||
NET_CON_STRUCT_COMMON
|
NET_CON_STRUCT_COMMON
|
||||||
struct kevent ev;
|
struct kevent ev_r;
|
||||||
|
struct kevent ev_w;
|
||||||
|
int change;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct net_backend_kqueue
|
struct net_backend_kqueue
|
||||||
{
|
{
|
||||||
int kqfd;
|
int kqfd;
|
||||||
struct net_connection_kqueue** conns;
|
struct net_connection_kqueue** conns;
|
||||||
struct kevent** changes;
|
struct kevent* changes;
|
||||||
size_t nchanges;
|
int* change_list;
|
||||||
|
size_t change_list_len;
|
||||||
struct kevent events[KQUEUE_EVBUFFER];
|
struct kevent events[KQUEUE_EVBUFFER];
|
||||||
struct net_backend_common* common;
|
struct net_backend_common* common;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define CHANGE_ACTION_ADD 0x0001
|
||||||
|
#define CHANGE_ACTION_MOD 0x0002
|
||||||
|
#define CHANGE_ACTION_DEL 0x0004
|
||||||
|
#define CHANGE_OP_WANT_READ 0x0100
|
||||||
|
#define CHANGE_OP_WANT_WRITE 0x0200
|
||||||
|
|
||||||
static void net_backend_set_handlers(struct net_backend_handler* handler);
|
static void net_backend_set_handlers(struct net_backend_handler* handler);
|
||||||
|
static void add_change(struct net_backend_kqueue* backend, struct net_connection_kqueue* con, int actions);
|
||||||
|
static size_t create_change_list(struct net_backend_kqueue* backend);
|
||||||
|
|
||||||
const char* net_backend_name_kqueue()
|
const char* net_backend_name_kqueue()
|
||||||
{
|
{
|
||||||
@@ -55,12 +66,13 @@ int net_backend_poll_kqueue(struct net_backend* data, int ms)
|
|||||||
int res;
|
int res;
|
||||||
struct timespec tspec = { 0, };
|
struct timespec tspec = { 0, };
|
||||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||||
|
size_t changes;
|
||||||
|
|
||||||
tspec.tv_sec = (ms / 1000);
|
tspec.tv_sec = (ms / 1000);
|
||||||
tspec.tv_nsec = ((ms % 1000) * 1000000); /* FIXME: correct? */
|
tspec.tv_nsec = ((ms % 1000) * 1000000);
|
||||||
|
|
||||||
res = kevent(backend->kqfd, *backend->changes, backend->nchanges, backend->events, KQUEUE_EVBUFFER, &tspec);
|
changes = create_change_list(backend);
|
||||||
backend->nchanges = 0;
|
res = kevent(backend->kqfd, backend->changes, changes, backend->events, KQUEUE_EVBUFFER, &tspec);
|
||||||
|
|
||||||
if (res == -1 && errno == EINTR)
|
if (res == -1 && errno == EINTR)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -75,12 +87,15 @@ void net_backend_process_kqueue(struct net_backend* data, int res)
|
|||||||
for (n = 0; n < res; n++)
|
for (n = 0; n < res; n++)
|
||||||
{
|
{
|
||||||
struct net_connection_kqueue* con = (struct net_connection_kqueue*) backend->events[n].udata;
|
struct net_connection_kqueue* con = (struct net_connection_kqueue*) backend->events[n].udata;
|
||||||
|
if (con && con->sd >= 0 && backend->conns[con->sd])
|
||||||
|
{
|
||||||
int ev = 0;
|
int ev = 0;
|
||||||
if (backend->events[n].filter & EVFILT_READ) ev |= NET_EVENT_READ;
|
if (backend->events[n].filter == EVFILT_READ) ev = NET_EVENT_READ;
|
||||||
if (backend->events[n].filter & EVFILT_WRITE) ev |= NET_EVENT_WRITE;
|
else if (backend->events[n].filter == EVFILT_WRITE) ev = NET_EVENT_WRITE;
|
||||||
net_con_callback((struct net_connection*) con, ev);
|
net_con_callback((struct net_connection*) con, ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct net_connection* net_con_create_kqueue(struct net_backend* data)
|
struct net_connection* net_con_create_kqueue(struct net_backend* data)
|
||||||
{
|
{
|
||||||
@@ -100,30 +115,37 @@ void net_con_initialize_kqueue(struct net_backend* data, struct net_connection*
|
|||||||
|
|
||||||
void net_con_backend_add_kqueue(struct net_backend* data, struct net_connection* con_, int events)
|
void net_con_backend_add_kqueue(struct net_backend* data, struct net_connection* con_, int events)
|
||||||
{
|
{
|
||||||
short filter = 0;
|
|
||||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||||
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||||
if (events & NET_EVENT_READ) filter |= EVFILT_READ;
|
int operation;
|
||||||
if (events & NET_EVENT_WRITE) filter |= EVFILT_READ;
|
|
||||||
EV_SET(&con->ev, con->sd, filter, EV_ADD, 0, 0, con);
|
|
||||||
backend->changes[backend->nchanges++] = &con->ev;
|
|
||||||
backend->conns[con->sd] = con;
|
backend->conns[con->sd] = con;
|
||||||
|
|
||||||
|
operation = CHANGE_ACTION_ADD;
|
||||||
|
|
||||||
|
if (events & NET_EVENT_READ)
|
||||||
|
operation |= CHANGE_OP_WANT_READ;
|
||||||
|
|
||||||
|
if (events & NET_EVENT_WRITE)
|
||||||
|
operation |= CHANGE_OP_WANT_WRITE;
|
||||||
|
|
||||||
|
add_change(backend, con, operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_con_backend_mod_kqueue(struct net_backend* data, struct net_connection* con_, int events)
|
void net_con_backend_mod_kqueue(struct net_backend* data, struct net_connection* con_, int events)
|
||||||
{
|
{
|
||||||
short filter = 0;
|
|
||||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||||
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||||
|
|
||||||
if (events & NET_EVENT_READ) filter |= EVFILT_READ;
|
int operation = CHANGE_ACTION_ADD;
|
||||||
if (events & NET_EVENT_WRITE) filter |= EVFILT_READ;
|
|
||||||
|
|
||||||
if (filter == con->ev.filter)
|
if (events & NET_EVENT_READ)
|
||||||
return;
|
operation |= CHANGE_OP_WANT_READ;
|
||||||
|
|
||||||
EV_SET(&con->ev, con->sd, filter, EV_ADD, 0, 0, con);
|
if (events & NET_EVENT_WRITE)
|
||||||
backend->changes[backend->nchanges++] = &con->ev;
|
operation |= CHANGE_OP_WANT_WRITE;
|
||||||
|
|
||||||
|
add_change(backend, con, operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_con_backend_del_kqueue(struct net_backend* data, struct net_connection* con_)
|
void net_con_backend_del_kqueue(struct net_backend* data, struct net_connection* con_)
|
||||||
@@ -131,10 +153,12 @@ void net_con_backend_del_kqueue(struct net_backend* data, struct net_connection*
|
|||||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||||
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||||
|
|
||||||
backend->conns[con->sd] = 0;
|
|
||||||
|
|
||||||
/* No need to remove it from the kqueue filter, the kqueue man page says
|
/* No need to remove it from the kqueue filter, the kqueue man page says
|
||||||
it is automatically removed when the descriptor is closed. */
|
it is automatically removed when the descriptor is closed... */
|
||||||
|
add_change(backend, con, CHANGE_ACTION_DEL);
|
||||||
|
|
||||||
|
// Unmap the socket descriptor.
|
||||||
|
backend->conns[con->sd] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_backend_shutdown_kqueue(struct net_backend* data)
|
void net_backend_shutdown_kqueue(struct net_backend* data)
|
||||||
@@ -143,6 +167,7 @@ void net_backend_shutdown_kqueue(struct net_backend* data)
|
|||||||
close(backend->kqfd);
|
close(backend->kqfd);
|
||||||
hub_free(backend->conns);
|
hub_free(backend->conns);
|
||||||
hub_free(backend->changes);
|
hub_free(backend->changes);
|
||||||
|
hub_free(backend->change_list);
|
||||||
hub_free(backend);
|
hub_free(backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,8 +187,8 @@ struct net_backend* net_backend_init_kqueue(struct net_backend_handler* handler,
|
|||||||
}
|
}
|
||||||
|
|
||||||
backend->conns = hub_malloc_zero(sizeof(struct net_connection_kqueue*) * common->max);
|
backend->conns = hub_malloc_zero(sizeof(struct net_connection_kqueue*) * common->max);
|
||||||
backend->conns = hub_malloc_zero(sizeof(struct net_connection_kqueue*) * common->max);
|
backend->changes = hub_malloc_zero(sizeof(struct kevent) * common->max * 2);
|
||||||
backend->changes = hub_malloc_zero(sizeof(struct kevent*) * common->max);
|
backend->change_list = hub_malloc_zero(sizeof(int) * common->max);
|
||||||
backend->common = common;
|
backend->common = common;
|
||||||
|
|
||||||
net_backend_set_handlers(handler);
|
net_backend_set_handlers(handler);
|
||||||
@@ -183,4 +208,71 @@ static void net_backend_set_handlers(struct net_backend_handler* handler)
|
|||||||
handler->con_del = net_con_backend_del_kqueue;
|
handler->con_del = net_con_backend_del_kqueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_change(struct net_backend_kqueue* backend, struct net_connection_kqueue* con, int actions)
|
||||||
|
{
|
||||||
|
if (actions && !con->change)
|
||||||
|
{
|
||||||
|
backend->change_list[backend->change_list_len++] = con->sd;
|
||||||
|
con->change = actions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t create_change_list(struct net_backend_kqueue* backend)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
size_t changes = 0;
|
||||||
|
int sd;
|
||||||
|
struct net_connection_kqueue* con;
|
||||||
|
unsigned short flags_r = 0;
|
||||||
|
unsigned short flags_w = 0;
|
||||||
|
|
||||||
|
for (; n < backend->change_list_len; n++)
|
||||||
|
{
|
||||||
|
sd = backend->change_list[n];
|
||||||
|
con = backend->conns[sd];
|
||||||
|
if (con)
|
||||||
|
{
|
||||||
|
flags_r = 0;
|
||||||
|
flags_w = 0;
|
||||||
|
|
||||||
|
if (con->change & CHANGE_ACTION_ADD)
|
||||||
|
{
|
||||||
|
flags_r |= EV_ADD;
|
||||||
|
flags_w |= EV_ADD;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con->change & CHANGE_OP_WANT_READ)
|
||||||
|
flags_r |= EV_ENABLE;
|
||||||
|
else
|
||||||
|
flags_r |= EV_DISABLE;
|
||||||
|
|
||||||
|
if (con->change & CHANGE_OP_WANT_WRITE)
|
||||||
|
flags_w |= EV_ENABLE;
|
||||||
|
else
|
||||||
|
flags_w |= EV_DISABLE;
|
||||||
|
|
||||||
|
if (con->ev_r.flags != flags_r)
|
||||||
|
{
|
||||||
|
EV_SET(&con->ev_r, sd, EVFILT_READ, flags_r, 0, 0, con);
|
||||||
|
memcpy(&backend->changes[changes++], &con->ev_r, sizeof(struct kevent));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con->ev_w.flags != flags_w)
|
||||||
|
{
|
||||||
|
EV_SET(&con->ev_w, sd, EVFILT_WRITE, flags_w, 0, 0, con);
|
||||||
|
memcpy(&backend->changes[changes++], &con->ev_w, sizeof(struct kevent));
|
||||||
|
}
|
||||||
|
|
||||||
|
con->change = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EV_SET(&backend->changes[changes++], sd, EVFILT_READ, EV_DELETE, 0, 0, 0);
|
||||||
|
EV_SET(&backend->changes[changes++], sd, EVFILT_READ, EV_DELETE, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
backend->change_list_len = 0;
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* USE_KQUEUE */
|
#endif /* USE_KQUEUE */
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ void timeout_evt_reset(struct timeout_evt* t)
|
|||||||
|
|
||||||
int timeout_evt_is_scheduled(struct timeout_evt* t)
|
int timeout_evt_is_scheduled(struct timeout_evt* t)
|
||||||
{
|
{
|
||||||
return !!t->prev;
|
return t->prev != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void timeout_queue_initialize(struct timeout_queue* t, time_t now, size_t max)
|
void timeout_queue_initialize(struct timeout_queue* t, time_t now, size_t max)
|
||||||
@@ -54,10 +54,11 @@ void timeout_queue_shutdown(struct timeout_queue* t)
|
|||||||
|
|
||||||
size_t timeout_queue_process(struct timeout_queue* t, time_t now)
|
size_t timeout_queue_process(struct timeout_queue* t, time_t now)
|
||||||
{
|
{
|
||||||
size_t pos;
|
size_t pos = t->last;
|
||||||
size_t events = 0;
|
size_t events = 0;
|
||||||
struct timeout_evt* evt = 0;
|
struct timeout_evt* evt = 0;
|
||||||
for (pos = t->last; pos <= now; pos++)
|
t->last = now;
|
||||||
|
for (; pos <= now; pos++)
|
||||||
{
|
{
|
||||||
while ((evt = t->events[pos % t->max]))
|
while ((evt = t->events[pos % t->max]))
|
||||||
{
|
{
|
||||||
@@ -66,7 +67,6 @@ size_t timeout_queue_process(struct timeout_queue* t, time_t now)
|
|||||||
events++;
|
events++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t->last = now;
|
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,6 +94,7 @@ void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size
|
|||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
|
uhub_assert(first->timestamp == evt->timestamp);
|
||||||
first->prev->next = evt;
|
first->prev->next = evt;
|
||||||
evt->prev = first->prev;
|
evt->prev = first->prev;
|
||||||
first->prev = evt;
|
first->prev = evt;
|
||||||
|
|||||||
153
src/plugin_api/handle.h
Normal file
153
src/plugin_api/handle.h
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_UHUB_PLUGIN_HANDLE_H
|
||||||
|
#define HAVE_UHUB_PLUGIN_HANDLE_H
|
||||||
|
|
||||||
|
#include "system.h"
|
||||||
|
#include "util/ipcalc.h"
|
||||||
|
|
||||||
|
#define PLUGIN_API_VERSION 0
|
||||||
|
|
||||||
|
#ifndef MAX_NICK_LEN
|
||||||
|
#define MAX_NICK_LEN 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX_PASS_LEN
|
||||||
|
#define MAX_PASS_LEN 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ip_addr_encap;
|
||||||
|
|
||||||
|
struct plugin_user
|
||||||
|
{
|
||||||
|
unsigned int sid;
|
||||||
|
const char* nick;
|
||||||
|
const char* cid;
|
||||||
|
struct ip_addr_encap addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum plugin_status
|
||||||
|
{
|
||||||
|
st_default = 0, /* Use default */
|
||||||
|
st_allow = 1, /* Allow action */
|
||||||
|
st_deny = -1, /* Deny action */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum plugin_status plugin_st;
|
||||||
|
|
||||||
|
enum auth_credentials
|
||||||
|
{
|
||||||
|
auth_cred_none, /**<<< "User has no credentials (not yet logged in)" */
|
||||||
|
auth_cred_bot, /**<<< "User is a robot" */
|
||||||
|
auth_cred_guest, /**<<< "User is a guest (unregistered user)" */
|
||||||
|
auth_cred_user, /**<<< "User is identified as a registered user" */
|
||||||
|
auth_cred_operator, /**<<< "User is identified as a hub operator" */
|
||||||
|
auth_cred_super, /**<<< "User is a super user" (not used) */
|
||||||
|
auth_cred_link, /**<<< "User is a link (not used currently)" */
|
||||||
|
auth_cred_admin, /**<<< "User is identified as a hub administrator/owner" */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct auth_info
|
||||||
|
{
|
||||||
|
char nickname[MAX_NICK_LEN+1];
|
||||||
|
char password[MAX_PASS_LEN+1];
|
||||||
|
enum auth_credentials credentials;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef plugin_st (*on_chat_msg_t)(struct plugin_user* from, const char* message);
|
||||||
|
typedef plugin_st (*on_private_msg_t)(struct plugin_user* from, struct plugin_user* to, const char* message);
|
||||||
|
typedef plugin_st (*on_search_t)(struct plugin_user* from, const char* data);
|
||||||
|
typedef plugin_st (*on_p2p_connect_t)(struct plugin_user* from, struct plugin_user* to);
|
||||||
|
typedef plugin_st (*on_p2p_revconnect_t)(struct plugin_user* from, struct plugin_user* to);
|
||||||
|
|
||||||
|
typedef void (*on_user_connect_t)(struct ip_addr_encap*);
|
||||||
|
typedef void (*on_user_login_t)(struct plugin_user*);
|
||||||
|
typedef void (*on_user_logout_t)(struct plugin_user*);
|
||||||
|
typedef void (*on_user_nick_change_t)(struct plugin_user*, const char* new_nick);
|
||||||
|
|
||||||
|
typedef plugin_st (*on_change_nick_t)(struct plugin_user*, const char* new_nick);
|
||||||
|
|
||||||
|
typedef plugin_st (*on_check_ip_early_t)(struct ip_addr_encap*);
|
||||||
|
typedef plugin_st (*on_check_ip_late_t)(struct ip_addr_encap*);
|
||||||
|
typedef plugin_st (*on_validate_nick_t)(const char* nick);
|
||||||
|
typedef plugin_st (*on_validate_cid_t)(const char* cid);
|
||||||
|
|
||||||
|
typedef int (*auth_get_user_t)(const char* nickname, struct auth_info* info);
|
||||||
|
typedef plugin_st (*auth_register_user_t)(struct auth_info* user);
|
||||||
|
typedef plugin_st (*auth_update_user_t)(struct auth_info* user);
|
||||||
|
typedef plugin_st (*auth_delete_user_t)(struct auth_info* user);
|
||||||
|
|
||||||
|
struct plugin_funcs
|
||||||
|
{
|
||||||
|
// Users logging in and out
|
||||||
|
on_user_connect_t on_user_connect; /* A user has connected to the hub */
|
||||||
|
on_user_login_t on_user_login; /* A user has successfully logged in to the hub */
|
||||||
|
on_user_logout_t on_user_logout; /* A user has logged out of the hub (was previously logged in) */
|
||||||
|
on_user_nick_change_t on_user_nick_change; /* A user has changed nickname */
|
||||||
|
|
||||||
|
// Activity events (can be intercepted and refused by a plugin)
|
||||||
|
on_chat_msg_t on_chat_msg; /* A public chat message is about to be sent (can be intercepted) */
|
||||||
|
on_private_msg_t on_private_msg; /* A public chat message is about to be sent (can be intercepted) */
|
||||||
|
on_search_t on_search; /* A search is about to be sent (can be intercepted) */
|
||||||
|
on_p2p_connect_t on_p2p_connect; /* A user is about to connect to another user (can be intercepted) */
|
||||||
|
on_p2p_revconnect_t on_p2p_revconnect; /* A user is about to connect to another user (can be intercepted) */
|
||||||
|
|
||||||
|
// Authentication actions.
|
||||||
|
auth_get_user_t auth_get_user; /* Get authentication info from plugin */
|
||||||
|
auth_register_user_t auth_register_user; /* Register user */
|
||||||
|
auth_update_user_t auth_update_user; /* Update a registered user */
|
||||||
|
auth_delete_user_t auth_delete_user; /* Delete a registered user */
|
||||||
|
|
||||||
|
// Login check functions
|
||||||
|
on_check_ip_early_t login_check_ip_early;
|
||||||
|
on_check_ip_late_t login_check_ip_late;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct uhub_plugin_handle
|
||||||
|
{
|
||||||
|
struct uhub_plugin* handle; /* Must NOT be modified by the plugin */
|
||||||
|
const char* name; /* plugin name */
|
||||||
|
const char* version; /* plugin version */
|
||||||
|
const char* description; /* plugin description */
|
||||||
|
void* ptr; /* Plugin specific data */
|
||||||
|
size_t plugin_api_version; /* Plugin API version */
|
||||||
|
size_t plugin_funcs_size; /* Size of the plugin funcs */
|
||||||
|
struct plugin_funcs funcs;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implemented by the plugin.
|
||||||
|
*
|
||||||
|
* @param handle[out] Sets all information by the plugin
|
||||||
|
* @param config A configuration string
|
||||||
|
* @return 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
extern int plugin_register(struct uhub_plugin_handle* handle, const char* config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
extern int plugin_unregister(struct uhub_plugin_handle*);
|
||||||
|
|
||||||
|
typedef int (*plugin_register_f)(struct uhub_plugin_handle* handle, const char* config);
|
||||||
|
typedef int (*plugin_unregister_f)(struct uhub_plugin_handle*);
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_PLUGIN_HANDLE_H */
|
||||||
28
src/plugins/mod_example.c
Normal file
28
src/plugins/mod_example.c
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* This is a minimal example plugin for uhub.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// #include "uhub.h"
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
|
int plugin_register(struct uhub_plugin_handle* plugin, const char* config)
|
||||||
|
{
|
||||||
|
plugin->name = "Example plugin";
|
||||||
|
plugin->version = "1.0";
|
||||||
|
plugin->description = "A simple example plugin";
|
||||||
|
plugin->ptr = NULL;
|
||||||
|
plugin->plugin_api_version = PLUGIN_API_VERSION;
|
||||||
|
plugin->plugin_funcs_size = sizeof(struct plugin_funcs);
|
||||||
|
memset(&plugin->funcs, 0, sizeof(struct plugin_funcs));
|
||||||
|
|
||||||
|
puts("plugin register");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_unregister(struct uhub_plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
/* No need to do anything! */
|
||||||
|
puts("plugin unregister");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
57
src/plugins/mod_logging.c
Normal file
57
src/plugins/mod_logging.c
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/**
|
||||||
|
* This is a minimal example plugin for uhub.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// #include "uhub.h"
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
|
struct ip_addr_encap;
|
||||||
|
|
||||||
|
plugin_st log_connect(struct ip_addr_encap* addr)
|
||||||
|
{
|
||||||
|
return st_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_user_login(struct plugin_user* user)
|
||||||
|
{
|
||||||
|
printf("login: \"%s\"\n", user->nick);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_user_logout(struct plugin_user* user)
|
||||||
|
{
|
||||||
|
printf("logout: \"%s\"\n", user->nick);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st log_change_nick(struct plugin_user* user, const char* new_nick)
|
||||||
|
{
|
||||||
|
printf("\"%s\" -> \"%s\"\n", user->nick, new_nick);
|
||||||
|
return st_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int plugin_register(struct uhub_plugin_handle* plugin, const char* config)
|
||||||
|
{
|
||||||
|
plugin->name = "Logging plugin";
|
||||||
|
plugin->version = "1.0";
|
||||||
|
plugin->description = "Logs users entering and leaving the hub.";
|
||||||
|
plugin->ptr = NULL;
|
||||||
|
plugin->plugin_api_version = PLUGIN_API_VERSION;
|
||||||
|
plugin->plugin_funcs_size = sizeof(struct plugin_funcs);
|
||||||
|
memset(&plugin->funcs, 0, sizeof(struct plugin_funcs));
|
||||||
|
|
||||||
|
plugin->funcs.on_connect = log_connect;
|
||||||
|
plugin->funcs.on_user_login = log_user_login;
|
||||||
|
plugin->funcs.on_user_logout = log_user_logout;
|
||||||
|
plugin->funcs.on_user_change_nick = log_change_nick;
|
||||||
|
|
||||||
|
puts("* plugin register");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_unregister(struct uhub_plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
/* No need to do anything! */
|
||||||
|
puts("* plugin unregister");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -89,6 +89,8 @@
|
|||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#define HAVE_STRNDUP
|
#define HAVE_STRNDUP
|
||||||
|
#define HAVE_DLOPEN
|
||||||
|
#include <dlfcn.h>
|
||||||
#ifndef __HAIKU__
|
#ifndef __HAIKU__
|
||||||
#define HAVE_MEMMEM
|
#define HAVE_MEMMEM
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
|
|
||||||
#define MAX_CID_LEN 39
|
#define MAX_CID_LEN 39
|
||||||
#define MAX_NICK_LEN 64
|
#define MAX_NICK_LEN 64
|
||||||
|
#define MAX_PASS_LEN 64
|
||||||
#define MAX_UA_LEN 32
|
#define MAX_UA_LEN 32
|
||||||
#define TIGERSIZE 24
|
#define TIGERSIZE 24
|
||||||
|
|
||||||
@@ -72,6 +73,7 @@ extern "C" {
|
|||||||
|
|
||||||
#include "core/auth.h"
|
#include "core/auth.h"
|
||||||
#include "core/config.h"
|
#include "core/config.h"
|
||||||
|
#include "core/floodctl.h"
|
||||||
#include "core/eventid.h"
|
#include "core/eventid.h"
|
||||||
#include "core/eventqueue.h"
|
#include "core/eventqueue.h"
|
||||||
#include "core/netevent.h"
|
#include "core/netevent.h"
|
||||||
@@ -79,10 +81,13 @@ extern "C" {
|
|||||||
#include "core/user.h"
|
#include "core/user.h"
|
||||||
#include "core/usermanager.h"
|
#include "core/usermanager.h"
|
||||||
#include "core/route.h"
|
#include "core/route.h"
|
||||||
|
#include "core/pluginloader.h"
|
||||||
#include "core/hub.h"
|
#include "core/hub.h"
|
||||||
#include "core/commands.h"
|
#include "core/commands.h"
|
||||||
#include "core/inf.h"
|
#include "core/inf.h"
|
||||||
#include "core/hubevent.h"
|
#include "core/hubevent.h"
|
||||||
|
#include "core/plugininvoke.h"
|
||||||
|
#include "core/pluginloader.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -400,3 +400,51 @@ const char* get_timestamp(time_t now)
|
|||||||
sprintf(ts, "[%02d:%02d]", t->tm_hour, t->tm_min);
|
sprintf(ts, "[%02d:%02d]", t->tm_hour, t->tm_min);
|
||||||
return ts;
|
return ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void strip_off_ini_line_comments(char* line, int line_count)
|
||||||
|
{
|
||||||
|
char* p = line;
|
||||||
|
char* out = line;
|
||||||
|
int backslash = 0;
|
||||||
|
|
||||||
|
if (!*line)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (; *p; p++)
|
||||||
|
{
|
||||||
|
if (!backslash)
|
||||||
|
{
|
||||||
|
if (*p == '\\')
|
||||||
|
{
|
||||||
|
backslash = 1;
|
||||||
|
}
|
||||||
|
else if (*p == '#')
|
||||||
|
{
|
||||||
|
*out = '\0';
|
||||||
|
out++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*out = *p;
|
||||||
|
out++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*p == '\\' || *p == '#' || *p == '\"')
|
||||||
|
{
|
||||||
|
*out = *p;
|
||||||
|
out++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_WARN("Invalid backslash escape on line %d", line_count);
|
||||||
|
*out = *p;
|
||||||
|
out++;
|
||||||
|
}
|
||||||
|
backslash = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*out = '\0';
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,10 +33,12 @@ extern int is_valid_base32_char(char c);
|
|||||||
extern void base32_encode(const unsigned char* buffer, size_t len, char* result);
|
extern void base32_encode(const unsigned char* buffer, size_t len, char* result);
|
||||||
extern void base32_decode(const char* src, unsigned char* dst, size_t len);
|
extern void base32_decode(const char* src, unsigned char* dst, size_t len);
|
||||||
extern char* strip_white_space(char* string);
|
extern char* strip_white_space(char* string);
|
||||||
|
extern void strip_off_ini_line_comments(char* line, int line_count);
|
||||||
|
|
||||||
extern int file_read_lines(const char* file, void* data, file_line_handler_t handler);
|
extern int file_read_lines(const char* file, void* data, file_line_handler_t handler);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern const char* uhub_itoa(int val);
|
extern const char* uhub_itoa(int val);
|
||||||
extern const char* uhub_ulltoa(uint64_t val);
|
extern const char* uhub_ulltoa(uint64_t val);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user