Compare commits
75 Commits
0.3.0-fina
...
0.3.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e816fd196 | ||
|
|
88a22659a1 | ||
|
|
3393ee6a85 | ||
|
|
58630fde08 | ||
|
|
8815118fde | ||
|
|
5454ae279a | ||
|
|
8e579f4601 | ||
|
|
e220357176 | ||
|
|
8bed952022 | ||
|
|
c4604a7e94 | ||
|
|
236daeae53 | ||
|
|
862c6a1baf | ||
|
|
198d86a1ee | ||
|
|
2ded9f3e09 | ||
|
|
59ed268f4d | ||
|
|
963416ad73 | ||
|
|
29c162727c | ||
|
|
1ce258bccf | ||
|
|
0de66286fa | ||
|
|
1a98bb6810 | ||
|
|
5e6879dffb | ||
|
|
1b56adb8c0 | ||
|
|
685597c795 | ||
|
|
782f091637 | ||
|
|
82eeaa1fba | ||
|
|
977b57a385 | ||
|
|
19b9f72337 | ||
|
|
56605f7dcb | ||
|
|
bf1b64db53 | ||
|
|
915cb56448 | ||
|
|
6992043f9d | ||
|
|
896bbfcb5d | ||
|
|
6ac78e1a10 | ||
|
|
74a2191350 | ||
|
|
be8db21561 | ||
|
|
8065903604 | ||
|
|
78ae9fb3ce | ||
|
|
4715815ba2 | ||
|
|
cb9625f6a5 | ||
|
|
9934bde050 | ||
|
|
9a1c5ee548 | ||
|
|
11df912162 | ||
|
|
c8bc2f64fd | ||
|
|
2dc95eca47 | ||
|
|
7637d9ba68 | ||
|
|
4e9488dd4d | ||
|
|
e0003ebbb2 | ||
|
|
8e7e8c68f5 | ||
|
|
db32eaeafc | ||
|
|
1599f63134 | ||
|
|
c3ad006d07 | ||
|
|
1faca92167 | ||
|
|
f0a13b4c23 | ||
|
|
ccd1c8f160 | ||
|
|
41418f21e7 | ||
|
|
7a8a737cad | ||
|
|
ac48ad01fb | ||
|
|
31a69b1f3f | ||
|
|
d7a1a52c1a | ||
|
|
f54e8dbbba | ||
|
|
de72d4ae63 | ||
|
|
01efc6cc20 | ||
|
|
7cf1181e6b | ||
|
|
4b64b28777 | ||
|
|
e9f0331ca8 | ||
|
|
f263534aaf | ||
|
|
788b644c80 | ||
|
|
2d7ffa37fe | ||
|
|
fbaac98483 | ||
|
|
bd9d8229ff | ||
|
|
dfa6d07455 | ||
|
|
6bbdd24cb7 | ||
|
|
e3a644a853 | ||
|
|
928225fb7b | ||
|
|
e3cf41cb97 |
2
AUTHORS
2
AUTHORS
@@ -2,5 +2,5 @@ Authors of uHub
|
||||
===============
|
||||
|
||||
Jan Vidar Krey, Design and implementation
|
||||
|
||||
E_zombie, Centos/RedHat customization scripts and heavy load testing
|
||||
|
||||
|
||||
8
BSDmakefile
Normal file
8
BSDmakefile
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
GMAKE=gmake
|
||||
|
||||
all:
|
||||
@${GMAKE} ${.TARGETS}
|
||||
|
||||
${.TARGETS}: all
|
||||
|
||||
12
ChangeLog
12
ChangeLog
@@ -1,3 +1,15 @@
|
||||
0.3.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:
|
||||
- More user commands: ban, broadcast, mute, rules, history, myip, whoip, log
|
||||
- Experimental SSL support
|
||||
|
||||
62
GNUmakefile
62
GNUmakefile
@@ -3,6 +3,8 @@
|
||||
## Copyright (C) 2007-2010, Jan Vidar Krey <janvidar@extatic.org>
|
||||
#
|
||||
|
||||
-include Makefile.private
|
||||
|
||||
CC = gcc
|
||||
LD := $(CC)
|
||||
MV := mv
|
||||
@@ -17,15 +19,22 @@ STACK_PROTECT ?= NO
|
||||
|
||||
ifeq ($(OS), Windows_NT)
|
||||
WINDOWS ?= YES
|
||||
OPSYS ?= Windows
|
||||
else
|
||||
OPSYS ?= $(shell uname)
|
||||
endif
|
||||
|
||||
ifeq (SOLARIS,YES)
|
||||
ifeq ($(OPSYS),SunOS)
|
||||
LDLIBS += -lsocket -lnsl
|
||||
endif
|
||||
|
||||
ifeq ($(OPSYS),Haiku)
|
||||
LDLIBS += -lnetwork
|
||||
endif
|
||||
|
||||
CFLAGS += -I./src/
|
||||
|
||||
ifeq ($(WINDOWS),YES)
|
||||
ifeq ($(OPSYS),Windows)
|
||||
USE_BIGENDIAN := NO
|
||||
LDLIBS += -lws2_32
|
||||
UHUB_CONF_DIR ?= c:/uhub/
|
||||
@@ -33,7 +42,6 @@ UHUB_PREFIX ?= c:/uhub/
|
||||
CFLAGS += -mno-cygwin
|
||||
LDFLAGS += -mno-cygwin
|
||||
BIN_EXT ?= .exe
|
||||
GIT_REVISION ?= NO
|
||||
else
|
||||
DESTDIR ?= /
|
||||
UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub
|
||||
@@ -44,7 +52,7 @@ BIN_EXT ?=
|
||||
endif
|
||||
|
||||
ifeq ($(SILENT),YES)
|
||||
MSG_CC=@echo " CC:" $(notdir $^) &&
|
||||
MSG_CC=@echo " CC:" $(notdir $<) &&
|
||||
MSG_LD=@echo " LD:" $(notdir $@) &&
|
||||
MSG_AR=@echo " AR:" $(notdir $@) &&
|
||||
else
|
||||
@@ -64,10 +72,8 @@ endif
|
||||
|
||||
ifeq ($(RELEASE),YES)
|
||||
CFLAGS += -O3 -DNDEBUG
|
||||
GIT_REVISION ?= NO
|
||||
else
|
||||
CFLAGS += -ggdb -DDEBUG
|
||||
GIT_REVISION ?= YES
|
||||
endif
|
||||
|
||||
ifeq ($(STACK_PROTECT),YES)
|
||||
@@ -112,9 +118,9 @@ CFLAGS += -DSSL_SUPPORT
|
||||
LDLIBS += -lssl
|
||||
endif
|
||||
|
||||
ifeq ($(GIT_REVISION),YES)
|
||||
CFLAGS += -DGIT_REVISION=\"$(shell git show --abbrev-commit | head -n 1 | cut -f 2 -d " ")\"
|
||||
endif
|
||||
GIT_VERSION=$(shell git describe --tags 2>/dev/null || echo "")
|
||||
GIT_REVISION=$(shell git show --abbrev-commit 2>/dev/null | head -n 1 | cut -f 2 -d " " || echo "")
|
||||
OLD_REVISION=$(shell grep GIT_REVISION revision.h 2>/dev/null | cut -f 3 -d " " | tr -d "\"")
|
||||
|
||||
# Sources
|
||||
libuhub_SOURCES := \
|
||||
@@ -122,6 +128,7 @@ libuhub_SOURCES := \
|
||||
src/core/commands.c \
|
||||
src/core/config.c \
|
||||
src/core/eventqueue.c \
|
||||
src/core/floodctl.c \
|
||||
src/core/hub.c \
|
||||
src/core/hubevent.c \
|
||||
src/core/hubio.c \
|
||||
@@ -134,8 +141,10 @@ libuhub_SOURCES := \
|
||||
src/network/backend.c \
|
||||
src/network/connection.c \
|
||||
src/network/epoll.c \
|
||||
src/network/kqueue.c \
|
||||
src/network/network.c \
|
||||
src/network/select.c \
|
||||
src/network/timeout.c \
|
||||
src/network/timer.c \
|
||||
src/util/ipcalc.c \
|
||||
src/util/list.c \
|
||||
@@ -143,7 +152,6 @@ libuhub_SOURCES := \
|
||||
src/util/memory.c \
|
||||
src/util/misc.c \
|
||||
src/util/rbtree.c \
|
||||
src/util/timeout.c \
|
||||
src/util/tiger.c
|
||||
|
||||
libadc_common_SOURCES := \
|
||||
@@ -160,16 +168,18 @@ adcrush_SOURCES := src/tools/adcrush.c
|
||||
admin_SOURCES := src/tools/admin.c
|
||||
|
||||
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_memory.tcc \
|
||||
autotest/test_ipfilter.tcc \
|
||||
autotest/test_inf.tcc \
|
||||
autotest/test_hub.tcc \
|
||||
autotest/test_message.tcc \
|
||||
autotest/test_misc.tcc \
|
||||
autotest/test_sid.tcc \
|
||||
autotest/test_tiger.tcc \
|
||||
autotest/test_usermanager.tcc \
|
||||
autotest/test_eventqueue.tcc
|
||||
autotest/test_timer.tcc \
|
||||
autotest/test_usermanager.tcc
|
||||
|
||||
autotest_OBJECTS = autotest.o
|
||||
|
||||
@@ -189,8 +199,10 @@ adcrush_BINARY=adcrush$(BIN_EXT)
|
||||
admin_BINARY=uhub-admin$(BIN_EXT)
|
||||
autotest_BINARY=autotest/test$(BIN_EXT)
|
||||
|
||||
%.o: %.c
|
||||
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@ $^
|
||||
.PHONY: revision.h.tmp
|
||||
|
||||
%.o: %.c version.h revision.h
|
||||
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
all: $(uhub_BINARY)
|
||||
|
||||
@@ -206,6 +218,18 @@ $(uhub_BINARY): $(uhub_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS)
|
||||
autotest.c: $(autotest_SOURCES)
|
||||
$(shell exotic --standalone $(autotest_SOURCES) > $@)
|
||||
|
||||
revision.h.tmp:
|
||||
@rm -f $@
|
||||
@echo "/* AUTOGENERATED FILE - DO NOT EDIT */" > $@
|
||||
@if [ -n '$(GIT_VERSION)' ]; then echo \#define GIT_VERSION \"$(GIT_VERSION)\" >> $@; fi
|
||||
@if [ -n '$(GIT_REVISION)' ]; then echo \#define GIT_REVISION \"$(GIT_REVISION)\" >> $@; fi
|
||||
|
||||
version.h: revision.h
|
||||
|
||||
revision.h: revision.h.tmp
|
||||
@if [ '$(GIT_REVISION)' != '$(OLD_REVISION)' ]; then cp $@.tmp $@; fi
|
||||
@if [ ! -f $@ ]; then cp $@.tmp $@; fi
|
||||
|
||||
$(autotest_OBJECTS): autotest.c
|
||||
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@ $<
|
||||
|
||||
@@ -233,7 +257,7 @@ dist-clean:
|
||||
@rm -rf $(all_OBJECTS) *~ core
|
||||
|
||||
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)
|
||||
|
||||
|
||||
|
||||
3
README
3
README
@@ -3,3 +3,6 @@ Welcome and thanks for downloading uHub, a high performance ADC p2p hub.
|
||||
For the official documentation, bugs and other information, please visit:
|
||||
http://www.uhub.org/
|
||||
|
||||
For a list of compatible ADC clients, see:
|
||||
http://www.adcportal.com/wiki/index.php/ADC_Software_List#Client_Software
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ EXO_TEST(hub_net_startup, {
|
||||
|
||||
EXO_TEST(hub_config_initialize, {
|
||||
config_defaults(&g_config);
|
||||
g_config.server_port = 15111;
|
||||
g_config.server_port = 65111;
|
||||
return 1;
|
||||
});
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@ static void inf_create_user()
|
||||
{
|
||||
if (inf_user) return;
|
||||
inf_user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
|
||||
inf_user->connection = net_con_create();
|
||||
inf_user->id.sid = 1;
|
||||
inf_user->limits.upload_slots = 1;
|
||||
}
|
||||
|
||||
@@ -8,27 +8,27 @@ EXO_TEST(test_message_refc_1, {
|
||||
});
|
||||
|
||||
EXO_TEST(test_message_refc_2, {
|
||||
return g_msg->references == 0; // 0
|
||||
return g_msg->references == 1;
|
||||
});
|
||||
|
||||
EXO_TEST(test_message_refc_3, {
|
||||
adc_msg_incref(g_msg);
|
||||
return g_msg->references == 1; // 1
|
||||
return g_msg->references == 2;
|
||||
});
|
||||
|
||||
EXO_TEST(test_message_refc_4, {
|
||||
adc_msg_incref(g_msg);
|
||||
return g_msg->references == 2; // 2
|
||||
return g_msg->references == 3;
|
||||
});
|
||||
|
||||
EXO_TEST(test_message_refc_5, {
|
||||
adc_msg_free(g_msg);
|
||||
return g_msg->references == 1; // 1
|
||||
return g_msg->references == 2;
|
||||
});
|
||||
|
||||
EXO_TEST(test_message_refc_6, {
|
||||
adc_msg_free(g_msg);
|
||||
return g_msg->references == 0; // 0
|
||||
return g_msg->references == 1;
|
||||
});
|
||||
|
||||
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;
|
||||
});
|
||||
19
debian/changelog
vendored
Normal file
19
debian/changelog
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
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
|
||||
|
||||
* Fixed init.d scripts.
|
||||
* Fixed lintian warnings.
|
||||
|
||||
-- Jan Vidar Krey <janvidar@extatic.org> Tue, 26 Jan 2010 19:02:02 +0100
|
||||
|
||||
uhub (0.3.0-1) unstable; urgency=low
|
||||
|
||||
* Initial Release.
|
||||
|
||||
-- Jan Vidar Krey <janvidar@extatic.org> Tue, 26 Jan 2010 18:59:02 +0100
|
||||
|
||||
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@@ -0,0 +1 @@
|
||||
7
|
||||
24
debian/control
vendored
Normal file
24
debian/control
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
Source: uhub
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Jan Vidar Krey <janvidar@extatic.org>
|
||||
Build-Depends: debhelper (>= 7.0.0)
|
||||
Standards-Version: 3.8.3.0
|
||||
|
||||
Package: uhub
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}
|
||||
Description: High performance ADC p2p hub
|
||||
uhub is a high performance peer-to-peer hub for the ADC network.
|
||||
Its low memory footprint allows it to handle several thousand users on
|
||||
high-end servers, or a small private hub on embedded hardware.
|
||||
.
|
||||
Key features:
|
||||
- High performance and low memory usage
|
||||
- IPv4 and IPv6 support
|
||||
- Experimental SSL support (optional)
|
||||
- Advanced access control support
|
||||
- Easy configuration
|
||||
.
|
||||
Homepage: http://www.uhub.org/
|
||||
|
||||
19
debian/copyright
vendored
Normal file
19
debian/copyright
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
uhub - High performance ADC p2p hub.
|
||||
Copyright (C) 2010 Jan Vidar Krey <janvidar@extatic.org>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
On Debian GNU/Linux systems, the complete text of the GNU General Public
|
||||
License can be found in `/usr/share/common-licenses/GPL'.
|
||||
|
||||
45
debian/rules
vendored
Executable file
45
debian/rules
vendored
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
# export DH_VERBOSE=1
|
||||
|
||||
makeopts := DESTDIR=$(shell pwd)/debian/uhub/ \
|
||||
UHUB_PREFIX=$(shell pwd)/debian/uhub/usr \
|
||||
RELEASE=YES SILENT=YES
|
||||
|
||||
build: build-stamp
|
||||
build-stamp:
|
||||
dh_testdir
|
||||
make $(makeopts)
|
||||
touch build-stamp
|
||||
|
||||
clean:
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
rm -f build-stamp
|
||||
make clean
|
||||
dh_clean
|
||||
|
||||
binary-indep: build
|
||||
|
||||
binary-arch: build
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_clean -k
|
||||
dh_installdirs
|
||||
$(MAKE) install $(makeopts)
|
||||
dh_installdocs
|
||||
dh_installinit
|
||||
dh_installlogrotate
|
||||
dh_installman -A
|
||||
dh_installchangelogs ChangeLog
|
||||
dh_strip
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_shlibdeps
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
|
||||
binary: binary-indep binary-arch
|
||||
.PHONY: build clean binary-indep binary-arch binary
|
||||
|
||||
4
debian/uhub.default
vendored
Normal file
4
debian/uhub.default
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# uhub - high performance adc hub.
|
||||
|
||||
UHUB_ENABLE=0
|
||||
|
||||
6
debian/uhub.dirs
vendored
Normal file
6
debian/uhub.dirs
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
etc/default
|
||||
etc/init.d
|
||||
etc/logrotate.d
|
||||
etc/uhub
|
||||
usr/bin
|
||||
var/log/uhub
|
||||
5
debian/uhub.docs
vendored
Normal file
5
debian/uhub.docs
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
AUTHORS
|
||||
README
|
||||
BUGS
|
||||
TODO
|
||||
doc/getstarted.txt
|
||||
92
debian/uhub.init
vendored
Normal file
92
debian/uhub.init
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: uhub
|
||||
# Required-Start: $remote_fs $network
|
||||
# Required-Stop: $remote_fs $network
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: uhub - High performance ADC p2p hub.
|
||||
### END INIT INFO
|
||||
|
||||
PATH=/sbin:/bin:/usr/sbin:/usr/bin
|
||||
|
||||
NAME=uhub
|
||||
DESC="ADC hub"
|
||||
DAEMON=/usr/bin/uhub
|
||||
PIDFILE=/var/run/uhub/uhub.pid
|
||||
LOGFILE=/var/log/uhub/uhub.log
|
||||
SCRIPTNAME=/etc/init.d/uhub
|
||||
|
||||
DEFAULTFILE=/etc/default/uhub
|
||||
[ -r $DEFAULTFILE ] && . $DEFAULTFILE
|
||||
|
||||
DAEMON_ENABLE="${UHUB_ENABLE}"
|
||||
DAEMON_OPTS="-l ${LOGFILE} -f -p ${PIDFILE}"
|
||||
|
||||
test -x $DAEMON || exit 0
|
||||
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
ulimit -n 65536
|
||||
mkdir -p /var/run/uhub/
|
||||
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
if [ "$DAEMON_ENABLE" != "true" ]; then
|
||||
log_daemon_msg "Disabled $DESC" $NAME
|
||||
log_end_msg 0
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log_daemon_msg "Starting $DESC" $NAME
|
||||
if ! start-stop-daemon --start --quiet --oknodo \
|
||||
--pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS
|
||||
then
|
||||
log_end_msg 1
|
||||
else
|
||||
log_end_msg 0
|
||||
fi
|
||||
;;
|
||||
|
||||
stop)
|
||||
log_daemon_msg "Stopping $DESC" $NAME
|
||||
if start-stop-daemon --quiet --stop --oknodo --retry 30 --oknodo \
|
||||
--pidfile $PIDFILE --exec $DAEMON
|
||||
then
|
||||
rm -f $PIDFILE
|
||||
log_end_msg 0
|
||||
else
|
||||
log_end_msg 1
|
||||
fi
|
||||
;;
|
||||
|
||||
reload)
|
||||
log_daemon_msg "Reloading $DESC configuration" $NAME
|
||||
if start-stop-daemon --stop --signal 2 --oknodo --retry 30 --oknodo \
|
||||
--quiet --pidfile $PIDFILE --exec $DAEMON
|
||||
then
|
||||
if start-stop-daemon --start --quiet \
|
||||
--pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS ; then
|
||||
log_end_msg 0
|
||||
else
|
||||
log_end_msg 1
|
||||
fi
|
||||
else
|
||||
log_end_msg 1
|
||||
fi
|
||||
;;
|
||||
|
||||
restart|force-reload)
|
||||
$0 stop
|
||||
$0 start
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
9
debian/uhub.logrotate
vendored
Normal file
9
debian/uhub.logrotate
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/var/log/uhub/*.log
|
||||
{
|
||||
compress
|
||||
size 10M
|
||||
rotate 10
|
||||
missingok
|
||||
notifempty
|
||||
}
|
||||
|
||||
1
debian/uhub.manpages
vendored
Normal file
1
debian/uhub.manpages
vendored
Normal file
@@ -0,0 +1 @@
|
||||
doc/uhub.1
|
||||
27
debian/uhub.postinst
vendored
Normal file
27
debian/uhub.postinst
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
chmod 0750 /var/log/uhub
|
||||
|
||||
if [ -x /etc/init.d/uhub ]; then
|
||||
update-rc.d uhub defaults >/dev/null
|
||||
|
||||
if [ -x /usr/sbin/invoke-rc.d ]; then
|
||||
invoke-rc.d uhub restart
|
||||
else
|
||||
/etc/init.d/uhub restart
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postinst: error: unknown argument: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
6
debian/uhub.postrm
vendored
Normal file
6
debian/uhub.postrm
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
if [ "$1" = purge ]; then
|
||||
update-rc.d uhub remove >/dev/null
|
||||
fi
|
||||
|
||||
10
debian/uhub.prerm
vendored
Normal file
10
debian/uhub.prerm
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
if [ "$1" = remove ]; then
|
||||
if command -v invoke-rc.d >/dev/null 2>&1; then
|
||||
invoke-rc.d uhub stop || true
|
||||
else
|
||||
/etc/init.d/uhub stop
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -8,19 +8,13 @@ Prerequisites
|
||||
Before you try to compile µHub, please make sure the following prerequisites are met.
|
||||
* GNU make
|
||||
* gcc > 3.0 (or MinGW on Windows)
|
||||
* libevent >= 1.3
|
||||
* Perl 5
|
||||
|
||||
Linux and Mac OSX
|
||||
-----------------
|
||||
Linux, Mac OSX, FreeBSD, NetBSD and OpenBSD
|
||||
-------------------------------------------
|
||||
Simply, run:
|
||||
% make
|
||||
|
||||
FreeBSD, NetBSD and OpenBSD
|
||||
---------------------------
|
||||
Use GNU make, not BSD make:
|
||||
% gmake
|
||||
|
||||
If you have an old gcc compiler, try disabling pre-compiled headers like this:
|
||||
gmake USE_PCH=NO
|
||||
|
||||
|
||||
@@ -43,4 +43,15 @@ if one wishes to run uhub as a specific user using the -u and -g switches.
|
||||
Example:
|
||||
% uhub -f -l mylog.txt -u nobody -g nogroup
|
||||
|
||||
|
||||
If you are planning to more than 1024 users on hub, you must increase the max number of file descriptors allowed.
|
||||
This limit needs to be higher than the configured max_users in uhub.conf.
|
||||
|
||||
In linux can add the following lines to /etc/security/limits.conf (allows for ~4000 users)
|
||||
* soft nofile 4096
|
||||
* hard nofile 4096
|
||||
|
||||
Or, you can use (as root):
|
||||
% ulimit -n 4096
|
||||
|
||||
Your mileage may vary -- Good luck!
|
||||
|
||||
@@ -38,7 +38,7 @@ RETVAL=0
|
||||
|
||||
|
||||
start() {
|
||||
KIND="UHUB"
|
||||
KIND="Uhub"
|
||||
echo -n $"Starting $KIND services: "
|
||||
daemon uhub $UHUBOPTIONS
|
||||
RETVAL=$?
|
||||
@@ -47,7 +47,7 @@ start() {
|
||||
}
|
||||
|
||||
stop() {
|
||||
KIND="UHUB"
|
||||
KIND="Uhub"
|
||||
echo -n $"Shutting down $KIND services: "
|
||||
killproc uhub
|
||||
RETVAL=$?
|
||||
|
||||
14
doc/init.d.RedHat/etc/logrotate.d/uhub
Normal file
14
doc/init.d.RedHat/etc/logrotate.d/uhub
Normal file
@@ -0,0 +1,14 @@
|
||||
# Log rotate for Uhub
|
||||
# see man logrotate
|
||||
#
|
||||
#
|
||||
/var/log/uhub.log {
|
||||
compress
|
||||
size 10M
|
||||
rotate 10
|
||||
missingok
|
||||
notifempty
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
# Log rotate for Uhub
|
||||
# see man logrotate
|
||||
#
|
||||
#
|
||||
/var/log/uhub.log {
|
||||
compress
|
||||
size 10M
|
||||
rotate 10
|
||||
missingok
|
||||
notifempty
|
||||
|
||||
|
||||
}
|
||||
@@ -9,7 +9,5 @@
|
||||
# -u <user> Run as given user
|
||||
# -g <group> Run with given group permissions
|
||||
# -p <file> Store pid in file (process id)
|
||||
|
||||
|
||||
UHUBOPTIONS=" -u uhub -f -p /var/run/uhub.pid -l /var/log/uhub.log"
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
# This file is read only to the uhub deamon, and if you
|
||||
# make changes to it while uhub is running you can send a
|
||||
# HUP signal to it ( $ killall -HUP uhub ), to reparse configuration (only on UNIX).
|
||||
# HUP signal to it ( $ killall -HUP uhub ), to reparse configuration (only on UNIX).
|
||||
# All configuration directives: http://www.uhub.org/config.php
|
||||
|
||||
# Bind to this port and address
|
||||
@@ -13,12 +13,18 @@
|
||||
server_port=1511
|
||||
server_bind_addr=any
|
||||
|
||||
# Alternative server ports
|
||||
# server_alt_ports = 1512, 1513
|
||||
|
||||
# The maximum amount of users allowed on the hub.
|
||||
max_users=500
|
||||
|
||||
# If 1, will show a "This hub is running uhub/version".
|
||||
# If 1, will show a "Powered by uHub/{VERSION}".
|
||||
show_banner=1
|
||||
|
||||
# If enabled then operating system and cpu architecture is part of the banner.
|
||||
show_banner_sys_info=1
|
||||
|
||||
# Allow only registered users on the hub if set to 1.
|
||||
registered_users_only=0
|
||||
|
||||
@@ -40,11 +46,11 @@ file_acl=/etc/uhub/users.conf
|
||||
file_motd=/etc/uhub/motd.txt
|
||||
|
||||
# This file can contain a rules of the hub.
|
||||
# Normally this message is sent to clients when write in chat !rules
|
||||
# Normally this message is sent to clients when write in chat !rules
|
||||
file_rules=/etc/uhub/rules.txt
|
||||
|
||||
|
||||
# Slots\share\hubs limits
|
||||
# Slots/share/hubs limits
|
||||
limit_max_hubs_user = 0
|
||||
limit_max_hubs_reg = 0
|
||||
limit_max_hubs_op = 0
|
||||
@@ -53,13 +59,32 @@ limit_min_hubs_user = 0
|
||||
limit_min_hubs_reg = 0
|
||||
limit_min_hubs_op = 0
|
||||
limit_min_share = 0
|
||||
# Example:
|
||||
# Example:
|
||||
# To require users to share at least 1 GB in order to enter the hub:
|
||||
# limit_min_share = 1024
|
||||
limit_max_share = 0
|
||||
limit_min_slots = 0
|
||||
limit_max_slots = 0
|
||||
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
|
||||
# if chat_is_privileged=yes only registered users may write in main chat
|
||||
chat_is_privileged = no
|
||||
|
||||
# if chat_only = yes then search and transfer functionality is disabled for
|
||||
# non-operator users.
|
||||
chat_only = no
|
||||
|
||||
# Configure status message as sent to clients in different circumstances.
|
||||
msg_hub_full = Hub is full
|
||||
@@ -91,5 +116,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_high = User is on too many hubs
|
||||
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.
|
||||
|
||||
|
||||
42
doc/uhub.ebuild
Normal file
42
doc/uhub.ebuild
Normal file
@@ -0,0 +1,42 @@
|
||||
# Copyright 1999-2010 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: $
|
||||
inherit eutils
|
||||
|
||||
if [ "$PV" != "9999" ]; then
|
||||
SRC_URI="http://www.extatic.org/downloads/uhub/${P}-src.tar.bz2"
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
else
|
||||
inherit git
|
||||
SRC_URI=""
|
||||
EGIT_REPO_URI="git://github.com/janvidar/uhub.git"
|
||||
KEYWORDS=""
|
||||
fi
|
||||
|
||||
EAPI="2"
|
||||
|
||||
DESCRIPTION="High performance ADC hub"
|
||||
HOMEPAGE="http://www.uhub.org/"
|
||||
|
||||
LICENSE="GPL-3"
|
||||
SLOT="0"
|
||||
IUSE="+ssl"
|
||||
|
||||
DEPEND="=dev-lang/perl-5*
|
||||
ssl? ( >=dev-libs/openssl-0.9.8 )
|
||||
"
|
||||
RDEPEND="${DEPEND}"
|
||||
src_compile() {
|
||||
$opts=""
|
||||
use ssl && opts="USE_SSL=YES $opts"
|
||||
emake $opts
|
||||
}
|
||||
src_install() {
|
||||
dodir /usr/bin
|
||||
dodir /etc/uhub
|
||||
emake DESTDIR="${D}" UHUB_PREFIX="${D}/usr" install || die "install failed"
|
||||
newinitd doc/uhub.gentoo.rc uhub || newinitd ${FILESDIR}/uhub.rc uhub
|
||||
}
|
||||
pkg_postinst() {
|
||||
enewuser uhub
|
||||
}
|
||||
85
doc/uhub.spec
Normal file
85
doc/uhub.spec
Normal file
@@ -0,0 +1,85 @@
|
||||
Summary: High performance ADC p2p hub.
|
||||
Name: uhub
|
||||
Version: 0.3.1
|
||||
Release: 3
|
||||
License: GPLv3
|
||||
Group: Networking/File transfer
|
||||
Source: uhub-%{version}.tar.gz
|
||||
URL: http://www.uhub.org
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
|
||||
|
||||
|
||||
%description
|
||||
uhub is a high performance peer-to-peer hub for the ADC network.
|
||||
Its low memory footprint allows it to handle several thousand users on
|
||||
high-end servers, or a small private hub on embedded hardware.
|
||||
|
||||
Key features:
|
||||
- High performance and low memory usage
|
||||
- IPv4 and IPv6 support
|
||||
- Experimental SSL support (optional)
|
||||
- Advanced access control support
|
||||
- Easy configuration
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}-%{version}
|
||||
|
||||
%build
|
||||
echo RPM_BUILD_ROOT = $RPM_BUILD_ROOT
|
||||
make
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/uhub
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/init.d
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/logrotate.d
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1
|
||||
|
||||
install uhub $RPM_BUILD_ROOT/usr/bin/
|
||||
> doc/motd.txt
|
||||
install -m644 doc/uhub.conf doc/users.conf doc/rules.txt doc/motd.txt $RPM_BUILD_ROOT/etc/uhub
|
||||
install doc/init.d.RedHat/etc/init.d/uhub $RPM_BUILD_ROOT/etc/init.d
|
||||
install -m644 doc/init.d.RedHat/etc/sysconfig/uhub $RPM_BUILD_ROOT/etc/sysconfig/
|
||||
install -m644 doc/init.d.RedHat/etc/logrotate.d/uhub $RPM_BUILD_ROOT/etc/logrotate.d/
|
||||
/bin/gzip -9c doc/uhub.1 > doc/uhub.1.gz &&
|
||||
install -m644 doc/uhub.1.gz $RPM_BUILD_ROOT/usr/share/man/man1
|
||||
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%doc AUTHORS BUGS COPYING ChangeLog README TODO doc/Doxyfile doc/architecture.txt doc/compile.txt doc/extensions.txt doc/getstarted.txt doc/uhub.dot
|
||||
%config(noreplace) /etc/uhub/uhub.conf
|
||||
#%{_sysconfdir}/uhub/uhub.conf
|
||||
%config(noreplace) %{_sysconfdir}/uhub/users.conf
|
||||
%config(noreplace) %{_sysconfdir}/uhub/motd.txt
|
||||
%config(noreplace) %{_sysconfdir}/uhub/rules.txt
|
||||
%{_sysconfdir}/init.d/uhub
|
||||
%config(noreplace) %{_sysconfdir}/logrotate.d/uhub
|
||||
%config(noreplace) %{_sysconfdir}/sysconfig/uhub
|
||||
/usr/share/man/man1/uhub.1.gz
|
||||
%{_bindir}/uhub
|
||||
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%post
|
||||
/sbin/chkconfig --add uhub
|
||||
if [ $1 -gt 1 ] ; then
|
||||
/etc/rc.d/init.d/uhub restart >/dev/null || :
|
||||
fi
|
||||
# need more informations about add services and users in system
|
||||
/usr/sbin/adduser -M -d /tmp -G nobody -s /sbin/nologin -c 'The Uhub ADC p2p hub Daemon' uhub >/dev/null 2>&1 ||:
|
||||
|
||||
%changelog
|
||||
* Tue Jan 31 2010 E_zombie
|
||||
- change GROUP
|
||||
- chmod for files
|
||||
- add postinstall scripts
|
||||
- fix "License"
|
||||
* Tue Jan 26 2010 E_zombie
|
||||
- first .spec release
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -26,7 +26,9 @@
|
||||
uhub_assert(X->capacity); \
|
||||
uhub_assert(X->length); \
|
||||
uhub_assert(X->length <= X->capacity); \
|
||||
uhub_assert(X->references > 0); \
|
||||
uhub_assert(X->length == strlen(X->cache));
|
||||
#define ADC_MSG_NULL_ON_FREE
|
||||
#else
|
||||
#define ADC_MSG_ASSERT(X) do { } while(0)
|
||||
#endif /* DEBUG */
|
||||
@@ -53,40 +55,18 @@ static void* msg_malloc_zero(size_t size)
|
||||
static void msg_free(void* 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
|
||||
|
||||
#define msg_malloc(X) hub_malloc(X)
|
||||
#define msg_malloc_zero(X) hub_malloc_zero(X)
|
||||
#define msg_free(X) hub_free(X)
|
||||
|
||||
#endif /* MSG_MEMORY_DEBUG */
|
||||
|
||||
|
||||
struct adc_message* adc_msg_incref(struct adc_message* msg)
|
||||
{
|
||||
if (!msg) return 0;
|
||||
#ifndef ADC_MESSAGE_INCREF
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_unprotect(msg);
|
||||
#endif
|
||||
msg->references++;
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_protect(msg);
|
||||
@@ -201,40 +181,35 @@ int adc_msg_is_empty(struct adc_message* msg)
|
||||
void adc_msg_free(struct adc_message* msg)
|
||||
{
|
||||
if (!msg) return;
|
||||
|
||||
|
||||
ADC_MSG_ASSERT(msg);
|
||||
|
||||
if (msg->references > 0)
|
||||
msg->references--;
|
||||
|
||||
if (msg->references == 0)
|
||||
{
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_unprotect(msg);
|
||||
#endif
|
||||
msg->references--;
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_protect(msg);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_unprotect(msg);
|
||||
#ifdef ADC_MSG_NULL_ON_FREE
|
||||
if (msg->cache)
|
||||
{
|
||||
*msg->cache = 0;
|
||||
}
|
||||
#endif
|
||||
msg_free(msg->cache);
|
||||
|
||||
|
||||
if (msg->feature_cast_include)
|
||||
{
|
||||
list_clear(msg->feature_cast_include, &hub_free);
|
||||
list_destroy(msg->feature_cast_include);
|
||||
msg->feature_cast_include = 0;
|
||||
}
|
||||
|
||||
|
||||
if (msg->feature_cast_exclude)
|
||||
{
|
||||
list_clear(msg->feature_cast_exclude, &hub_free);
|
||||
list_destroy(msg->feature_cast_exclude);
|
||||
msg->feature_cast_exclude = 0;
|
||||
}
|
||||
|
||||
|
||||
msg_free(msg);
|
||||
}
|
||||
}
|
||||
@@ -256,7 +231,7 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
||||
copy->length = cmd->length;
|
||||
copy->capacity = 0;
|
||||
copy->priority = cmd->priority;
|
||||
copy->references = 0;
|
||||
copy->references = 1;
|
||||
copy->feature_cast_include = 0;
|
||||
copy->feature_cast_exclude = 0;
|
||||
|
||||
@@ -295,9 +270,6 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
||||
|
||||
ADC_MSG_ASSERT(copy);
|
||||
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_protect(copy);
|
||||
#endif
|
||||
return copy;
|
||||
}
|
||||
|
||||
@@ -332,7 +304,7 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
|
||||
if (command == NULL)
|
||||
return NULL; /* OOM */
|
||||
|
||||
|
||||
if (!is_printable_utf8(line, length))
|
||||
{
|
||||
LOG_DEBUG("Dropped message with non-printable UTF-8 characters.");
|
||||
@@ -350,17 +322,18 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
msg_free(command);
|
||||
return NULL; /* OOM */
|
||||
}
|
||||
|
||||
|
||||
adc_msg_set_length(command, length + need_terminate);
|
||||
memcpy(command->cache, line, length);
|
||||
|
||||
|
||||
/* Ensure we are zero terminated */
|
||||
command->cache[length] = 0;
|
||||
command->cache[length+need_terminate] = 0;
|
||||
|
||||
|
||||
command->cmd = FOURCC(line[0], line[1], line[2], line[3]);
|
||||
command->priority = 0;
|
||||
|
||||
command->references = 1;
|
||||
|
||||
switch (prefix)
|
||||
{
|
||||
case 'U':
|
||||
@@ -368,12 +341,12 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
/* these should never be seen on a hub */
|
||||
ok = 0;
|
||||
break;
|
||||
|
||||
|
||||
case 'I':
|
||||
case 'H':
|
||||
ok = (length > 3);
|
||||
break;
|
||||
|
||||
|
||||
case 'B':
|
||||
ok = (length > 8 &&
|
||||
is_space(line[4]) &&
|
||||
@@ -381,18 +354,18 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
is_valid_base32_char(line[6]) &&
|
||||
is_valid_base32_char(line[7]) &&
|
||||
is_valid_base32_char(line[8]));
|
||||
|
||||
|
||||
if (!ok) break;
|
||||
|
||||
|
||||
temp_sid[0] = line[5];
|
||||
temp_sid[1] = line[6];
|
||||
temp_sid[2] = line[7];
|
||||
temp_sid[3] = line[8];
|
||||
temp_sid[4] = '\0';
|
||||
|
||||
|
||||
command->source = string_to_sid(temp_sid);
|
||||
break;
|
||||
|
||||
|
||||
case 'F':
|
||||
ok = (length > 8 &&
|
||||
is_space(line[4]) &&
|
||||
@@ -400,21 +373,21 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
is_valid_base32_char(line[6]) &&
|
||||
is_valid_base32_char(line[7]) &&
|
||||
is_valid_base32_char(line[8]));
|
||||
|
||||
|
||||
if (!ok) break;
|
||||
|
||||
|
||||
temp_sid[0] = line[5];
|
||||
temp_sid[1] = line[6];
|
||||
temp_sid[2] = line[7];
|
||||
temp_sid[3] = line[8];
|
||||
temp_sid[4] = '\0';
|
||||
|
||||
|
||||
command->source = string_to_sid(temp_sid);
|
||||
|
||||
|
||||
/* Create feature cast lists */
|
||||
command->feature_cast_include = list_create();
|
||||
command->feature_cast_exclude = list_create();
|
||||
|
||||
|
||||
if (!command->feature_cast_include || !command->feature_cast_exclude)
|
||||
{
|
||||
list_destroy(command->feature_cast_include);
|
||||
@@ -423,7 +396,7 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
msg_free(command);
|
||||
return NULL; /* OOM */
|
||||
}
|
||||
|
||||
|
||||
n = 10;
|
||||
while (line[n] == '+' || line[n] == '-')
|
||||
{
|
||||
@@ -431,21 +404,20 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
feature_cast_list = command->feature_cast_include;
|
||||
else
|
||||
feature_cast_list = command->feature_cast_exclude;
|
||||
|
||||
|
||||
temp_sid[0] = line[n++];
|
||||
temp_sid[1] = line[n++];
|
||||
temp_sid[2] = line[n++];
|
||||
temp_sid[3] = line[n++];
|
||||
temp_sid[4] = '\0';
|
||||
|
||||
|
||||
list_append(feature_cast_list, hub_strdup(temp_sid));
|
||||
}
|
||||
|
||||
|
||||
if (n == 10)
|
||||
ok = 0;
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'D':
|
||||
case 'E':
|
||||
ok = (length > 13 &&
|
||||
@@ -459,41 +431,41 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
is_valid_base32_char(line[11]) &&
|
||||
is_valid_base32_char(line[12]) &&
|
||||
is_valid_base32_char(line[13]));
|
||||
|
||||
|
||||
if (!ok) break;
|
||||
|
||||
|
||||
temp_sid[0] = line[5];
|
||||
temp_sid[1] = line[6];
|
||||
temp_sid[2] = line[7];
|
||||
temp_sid[3] = line[8];
|
||||
temp_sid[4] = '\0';
|
||||
|
||||
|
||||
command->source = string_to_sid(temp_sid);
|
||||
|
||||
|
||||
temp_sid[0] = line[10];
|
||||
temp_sid[1] = line[11];
|
||||
temp_sid[2] = line[12];
|
||||
temp_sid[3] = line[13];
|
||||
temp_sid[4] = '\0';
|
||||
|
||||
|
||||
command->target = string_to_sid(temp_sid);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
|
||||
if (need_terminate)
|
||||
{
|
||||
command->cache[length] = '\n';
|
||||
}
|
||||
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
adc_msg_free(command);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* At this point the arg_offset should point to a space, or the end of message */
|
||||
n = adc_msg_get_arg_offset(command);
|
||||
if (command->cache[n] == ' ')
|
||||
@@ -502,18 +474,14 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
}
|
||||
else if (command->cache[n] == '\n') ok = 1;
|
||||
else ok = 0;
|
||||
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
adc_msg_free(command);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ADC_MSG_ASSERT(command);
|
||||
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_protect(command);
|
||||
#endif
|
||||
ADC_MSG_ASSERT(command);
|
||||
return command;
|
||||
}
|
||||
|
||||
@@ -527,7 +495,6 @@ struct adc_message* adc_msg_create(const char* line)
|
||||
struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
||||
{
|
||||
struct adc_message* msg = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
|
||||
|
||||
if (!msg)
|
||||
return NULL; /* OOM */
|
||||
|
||||
@@ -538,7 +505,7 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
||||
msg_free(msg);
|
||||
return NULL; /* OOM */
|
||||
}
|
||||
|
||||
|
||||
if (fourcc)
|
||||
{
|
||||
msg->cache[0] = (char) ((fourcc >> 24) & 0xff);
|
||||
@@ -546,19 +513,15 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
||||
msg->cache[2] = (char) ((fourcc >> 8) & 0xff);
|
||||
msg->cache[3] = (char) ((fourcc ) & 0xff);
|
||||
msg->cache[4] = '\n';
|
||||
|
||||
|
||||
/* Ensure we are zero terminated */
|
||||
adc_msg_set_length(msg, 5);
|
||||
msg->cache[msg->length] = 0;
|
||||
}
|
||||
|
||||
|
||||
msg->cmd = fourcc;
|
||||
msg->priority = 0;
|
||||
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_protect(msg);
|
||||
#endif
|
||||
|
||||
msg->references = 1;
|
||||
return msg;
|
||||
}
|
||||
|
||||
@@ -625,7 +588,7 @@ int adc_msg_has_named_argument(struct adc_message* cmd, const char prefix_[2])
|
||||
int arg_offset = adc_msg_get_arg_offset(cmd);
|
||||
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
|
||||
start = memmem(&cmd->cache[arg_offset], (cmd->length - arg_offset), prefix, 3);
|
||||
while (start)
|
||||
{
|
||||
@@ -635,7 +598,7 @@ int adc_msg_has_named_argument(struct adc_message* cmd, const char prefix_[2])
|
||||
else
|
||||
start = NULL;
|
||||
}
|
||||
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -648,25 +611,25 @@ char* adc_msg_get_named_argument(struct adc_message* cmd, const char prefix_[2])
|
||||
size_t length;
|
||||
char prefix[4] = { ' ', prefix_[0], prefix_[1], '\0' };
|
||||
int arg_offset = adc_msg_get_arg_offset(cmd);
|
||||
|
||||
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
|
||||
start = memmem(&cmd->cache[arg_offset], cmd->length - arg_offset, prefix, 3);
|
||||
if (!start)
|
||||
return NULL;
|
||||
|
||||
|
||||
start = &start[3];
|
||||
end = strchr(start, ' ');
|
||||
if (!end) end = &cmd->cache[cmd->length];
|
||||
length = &end[0] - &start[0];
|
||||
|
||||
|
||||
argument = hub_strndup(start, length);
|
||||
|
||||
if (length > 0 && argument[length-1] == '\n')
|
||||
{
|
||||
argument[length-1] = 0;
|
||||
}
|
||||
|
||||
|
||||
return argument;
|
||||
}
|
||||
|
||||
@@ -684,9 +647,9 @@ int adc_msg_replace_named_argument(struct adc_message* cmd, const char prefix[2]
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -698,10 +661,6 @@ void adc_msg_terminate(struct adc_message* cmd)
|
||||
adc_msg_cache_append(cmd, "\n", 1);
|
||||
}
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_protect(cmd);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* FIXME: this looks bogus */
|
||||
@@ -709,10 +668,6 @@ void adc_msg_unterminate(struct adc_message* cmd)
|
||||
{
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_unprotect(cmd);
|
||||
#endif
|
||||
|
||||
if (cmd->length > 0 && cmd->cache[cmd->length-1] == '\n')
|
||||
{
|
||||
cmd->length--;
|
||||
@@ -725,9 +680,9 @@ int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], co
|
||||
int ret = 0;
|
||||
if (!string)
|
||||
return -1;
|
||||
|
||||
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
|
||||
adc_msg_unterminate(cmd);
|
||||
adc_msg_cache_append(cmd, " ", 1);
|
||||
adc_msg_cache_append(cmd, prefix, 2);
|
||||
@@ -761,7 +716,7 @@ int adc_msg_add_named_argument_uint64(struct adc_message* cmd, const char prefix
|
||||
int adc_msg_add_argument(struct adc_message* cmd, const char* string)
|
||||
{
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
|
||||
adc_msg_unterminate(cmd);
|
||||
adc_msg_cache_append(cmd, " ", 1);
|
||||
adc_msg_cache_append(cmd, string, strlen(string));
|
||||
@@ -827,11 +782,11 @@ int adc_msg_get_argument_index(struct adc_message* cmd, const char prefix[2])
|
||||
char* start;
|
||||
char* end;
|
||||
int count = 0;
|
||||
|
||||
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
|
||||
adc_msg_unterminate(cmd);
|
||||
|
||||
|
||||
start = strchr(&cmd->cache[adc_msg_get_arg_offset(cmd)-1], ' ');
|
||||
while (start)
|
||||
{
|
||||
@@ -884,16 +839,13 @@ int adc_msg_unescape_length(const char* str)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
char* adc_msg_unescape(const char* string)
|
||||
{
|
||||
char* new_string = msg_malloc(adc_msg_unescape_length(string)+1);
|
||||
char* ptr = (char*) new_string;
|
||||
char* str = (char*) string;
|
||||
int escaped = 0;
|
||||
|
||||
|
||||
while (*str)
|
||||
{
|
||||
if (escaped) {
|
||||
@@ -905,14 +857,12 @@ char* adc_msg_unescape(const char* string)
|
||||
*ptr++ = '\n';
|
||||
else
|
||||
*ptr++ = *str;
|
||||
|
||||
escaped = 0;
|
||||
} else {
|
||||
if (*str == '\\')
|
||||
escaped = 1;
|
||||
else
|
||||
*ptr++ = *str;
|
||||
|
||||
}
|
||||
str++;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -119,6 +119,14 @@ void sid_pool_destroy(struct sid_pool* pool)
|
||||
|
||||
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);
|
||||
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)
|
||||
{
|
||||
if (!sid || (sid > pool->max))
|
||||
if (!sid || (sid >= pool->max))
|
||||
return 0;
|
||||
return pool->map[sid];
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ static void add_ip_range(struct linked_list* list, struct ip_range* info)
|
||||
{
|
||||
char buf1[INET6_ADDRSTRLEN+1];
|
||||
char buf2[INET6_ADDRSTRLEN+1];
|
||||
|
||||
|
||||
if (info->lo.af == AF_INET)
|
||||
{
|
||||
net_address_to_string(AF_INET, &info->lo.internal_ip_data.in.s_addr, buf1, INET6_ADDRSTRLEN);
|
||||
@@ -130,8 +130,8 @@ static void add_ip_range(struct linked_list* list, struct ip_range* info)
|
||||
net_address_to_string(AF_INET6, &info->lo.internal_ip_data.in6, buf1, INET6_ADDRSTRLEN);
|
||||
net_address_to_string(AF_INET6, &info->hi.internal_ip_data.in6, buf2, INET6_ADDRSTRLEN);
|
||||
}
|
||||
LOG_DEBUG("ACL: Deny access for: %s-%s", buf1, buf2);
|
||||
|
||||
LOG_DEBUG("ACL: Added ip range: %s-%s", buf1, buf2);
|
||||
|
||||
list_append(list, info);
|
||||
}
|
||||
|
||||
@@ -326,7 +326,7 @@ struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, cons
|
||||
}
|
||||
|
||||
#define STR_LIST_CONTAINS(LIST, STR) \
|
||||
char* str = (char*) list_get_first(LIST); \
|
||||
str = (char*) list_get_first(LIST); \
|
||||
while (str) \
|
||||
{ \
|
||||
if (strcasecmp(str, STR) == 0) \
|
||||
@@ -337,18 +337,21 @@ struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, cons
|
||||
|
||||
int acl_is_cid_banned(struct acl_handle* handle, const char* data)
|
||||
{
|
||||
char* str;
|
||||
if (!handle) return 0;
|
||||
STR_LIST_CONTAINS(handle->cids, data);
|
||||
}
|
||||
|
||||
int acl_is_user_banned(struct acl_handle* handle, const char* data)
|
||||
{
|
||||
char* str;
|
||||
if (!handle) return 0;
|
||||
STR_LIST_CONTAINS(handle->users_banned, data);
|
||||
}
|
||||
|
||||
int acl_is_user_denied(struct acl_handle* handle, const char* data)
|
||||
{
|
||||
char* str;
|
||||
if (!handle) return 0;
|
||||
STR_LIST_CONTAINS(handle->users_denied, data);
|
||||
}
|
||||
|
||||
@@ -63,20 +63,23 @@ static void command_destroy(struct hub_command* cmd)
|
||||
|
||||
static struct hub_command* command_create(const char* message)
|
||||
{
|
||||
char* prefix;
|
||||
int n;
|
||||
struct hub_command* cmd = hub_malloc_zero(sizeof(struct hub_command));
|
||||
|
||||
if (!cmd) return 0;
|
||||
|
||||
cmd->message = message;
|
||||
cmd->args = list_create();
|
||||
|
||||
int n = split_string(message, "\\s", cmd->args, 0);
|
||||
n = split_string(message, "\\s", cmd->args, 0);
|
||||
if (n <= 0)
|
||||
{
|
||||
command_destroy(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* prefix = list_get_first(cmd->args);
|
||||
prefix = list_get_first(cmd->args);
|
||||
if (prefix && prefix[0] && prefix[1])
|
||||
{
|
||||
cmd->prefix = hub_strdup(&prefix[1]);
|
||||
@@ -129,8 +132,8 @@ static int command_status_user_not_found(struct hub_info* hub, struct hub_user*
|
||||
const char* command_get_syntax(struct commands_handler* handler)
|
||||
{
|
||||
static char args[128];
|
||||
args[0] = 0;
|
||||
size_t n = 0;
|
||||
args[0] = 0;
|
||||
if (handler->args)
|
||||
{
|
||||
for (n = 0; n < strlen(handler->args); n++)
|
||||
@@ -235,10 +238,11 @@ static int command_uptime(struct hub_info* hub, struct hub_user* user, struct hu
|
||||
static int command_kick(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||
{
|
||||
char* nick = list_get_first(cmd->args);
|
||||
struct hub_user* target;
|
||||
if (!nick)
|
||||
return -1; // FIXME: bad syntax.
|
||||
|
||||
struct hub_user* target = uman_get_user_by_nick(hub, nick);
|
||||
target = uman_get_user_by_nick(hub, nick);
|
||||
|
||||
if (!target)
|
||||
return command_status_user_not_found(hub, user, cmd, nick);
|
||||
@@ -253,10 +257,11 @@ static int command_kick(struct hub_info* hub, struct hub_user* user, struct hub_
|
||||
static int command_ban(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||
{
|
||||
char* nick = list_get_first(cmd->args);
|
||||
struct hub_user* target;
|
||||
if (!nick)
|
||||
return -1; // FIXME: bad syntax.
|
||||
|
||||
struct hub_user* target = uman_get_user_by_nick(hub, nick);
|
||||
target = uman_get_user_by_nick(hub, nick);
|
||||
|
||||
if (!target)
|
||||
return command_status_user_not_found(hub, user, cmd, nick);
|
||||
@@ -279,10 +284,11 @@ static int command_unban(struct hub_info* hub, struct hub_user* user, struct hub
|
||||
static int command_mute(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||
{
|
||||
char* nick = list_get_first(cmd->args);
|
||||
struct hub_user* target;
|
||||
if (!nick)
|
||||
return -1; // FIXME: bad syntax.
|
||||
|
||||
struct hub_user* target = uman_get_user_by_nick(hub, nick);
|
||||
target = uman_get_user_by_nick(hub, nick);
|
||||
|
||||
if (!target)
|
||||
return command_status_user_not_found(hub, user, cmd, nick);
|
||||
@@ -312,7 +318,12 @@ static int command_shutdown(struct hub_info* hub, struct hub_user* user, struct
|
||||
|
||||
static int command_version(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||
{
|
||||
return command_status(hub, user, cmd, "Powered by " PRODUCT "/" VERSION);
|
||||
const char* tmp;
|
||||
if (hub->config->show_banner_sys_info)
|
||||
tmp = "Powered by " PRODUCT_STRING " on " OPSYS "/" CPUINFO;
|
||||
else
|
||||
tmp = "Powered by " PRODUCT_STRING;
|
||||
return command_status(hub, user, cmd, tmp);
|
||||
}
|
||||
|
||||
static int command_myip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||
@@ -325,17 +336,18 @@ static int command_myip(struct hub_info* hub, struct hub_user* user, struct hub_
|
||||
static int command_getip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||
{
|
||||
char tmp[128];
|
||||
|
||||
char* nick = list_get_first(cmd->args);
|
||||
if (!nick);
|
||||
struct hub_user* target;
|
||||
|
||||
if (!nick)
|
||||
return -1; // FIXME: bad syntax/OOM
|
||||
|
||||
struct hub_user* target = uman_get_user_by_nick(hub, nick);
|
||||
target = uman_get_user_by_nick(hub, nick);
|
||||
|
||||
if (!target)
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -346,6 +358,8 @@ static int command_whoip(struct hub_info* hub, struct hub_user* user, struct hub
|
||||
struct linked_list* users;
|
||||
struct hub_user* u;
|
||||
int ret = 0;
|
||||
char tmp[128];
|
||||
char* buffer;
|
||||
|
||||
if (!address)
|
||||
return -1; // FIXME: bad syntax.
|
||||
@@ -366,10 +380,9 @@ static int command_whoip(struct hub_info* hub, struct hub_user* user, struct hub
|
||||
return command_status(hub, user, cmd, "No users found.");
|
||||
}
|
||||
|
||||
char tmp[128];
|
||||
snprintf(tmp, 128, "*** %s: Found %d match%s:", cmd->prefix, ret, ((ret != 1) ? "es" : ""));
|
||||
|
||||
char* buffer = hub_malloc(((MAX_NICK_LEN + INET6_ADDRSTRLEN + 5) * ret) + strlen(tmp) + 3);
|
||||
buffer = hub_malloc(((MAX_NICK_LEN + INET6_ADDRSTRLEN + 5) * ret) + strlen(tmp) + 3);
|
||||
if (!buffer)
|
||||
{
|
||||
list_destroy(users);
|
||||
@@ -413,13 +426,13 @@ static int command_history(struct hub_info* hub, struct hub_user* user, struct h
|
||||
char* message = 0;
|
||||
int ret = (int) list_size(messages);
|
||||
size_t bufsize;
|
||||
char tmp[128];
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
return command_status(hub, user, cmd, "No messages.");
|
||||
}
|
||||
|
||||
char tmp[128];
|
||||
snprintf(tmp, 128, "*** %s: Found %d message%s:", cmd->prefix, ret, ((ret != 1) ? "s" : ""));
|
||||
bufsize = strlen(tmp);
|
||||
message = (char*) list_get_first(messages);
|
||||
|
||||
@@ -111,6 +111,7 @@
|
||||
#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
|
||||
@@ -124,7 +125,9 @@
|
||||
#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_OBSOLETE_CLIENTS 0
|
||||
#define DEF_CHAT_ONLY 0
|
||||
#define DEF_CHAT_IS_PRIVILEGED 0
|
||||
#define DEF_LOW_BANDWIDTH_MODE 0
|
||||
@@ -139,6 +142,12 @@
|
||||
#define DEF_LIMIT_MAX_SHARE 0
|
||||
#define DEF_LIMIT_MIN_SLOTS 0
|
||||
#define DEF_LIMIT_MAX_SLOTS 0
|
||||
#define DEF_FLOOD_INTERVAL 0
|
||||
#define DEF_FLOOD_CHAT 0
|
||||
#define DEF_FLOOD_CONNECT 0
|
||||
#define DEF_FLOOD_SEARCH 0
|
||||
#define DEF_FLOOD_UPDATE 0
|
||||
#define DEF_FLOOD_EXTRAS 0
|
||||
#define DEF_TLS_ENABLE 0
|
||||
#define DEF_TLS_REQUIRE 1
|
||||
#define DEF_TLS_PRIVATE_KEY ""
|
||||
@@ -172,6 +181,13 @@
|
||||
#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."
|
||||
#define DEF_MSG_FLOOD_CHAT "Chat flood detected, messages are dropped."
|
||||
#define DEF_MSG_FLOOD_CONNECT "Connect flood detected, connection refused."
|
||||
#define DEF_MSG_FLOOD_SEARCH "Search flood detected, search is stopped."
|
||||
#define DEF_MSG_FLOOD_UPDATE "Update flood detected."
|
||||
#define DEF_MSG_FLOOD_EXTRAS "Flood detected."
|
||||
#define DEF_MSG_PROTO_NO_COMMON_HASH "No common hash algorithm."
|
||||
#define DEF_MSG_PROTO_OBSOLETE_ADC0 "Your client does not support ADC/1.0."
|
||||
|
||||
void config_defaults(struct hub_config* config)
|
||||
{
|
||||
@@ -184,6 +200,7 @@ void config_defaults(struct hub_config* config)
|
||||
DEFAULT_STRING (file_rules, DEF_FILE_RULES);
|
||||
DEFAULT_INTEGER(server_port, DEF_SERVER_PORT);
|
||||
DEFAULT_INTEGER(server_listen_backlog, DEF_SERVER_BACKLOG);
|
||||
DEFAULT_STRING (server_alt_ports, DEF_SERVER_ALT_PORTS);
|
||||
DEFAULT_INTEGER(max_users, DEF_MAX_USERS);
|
||||
DEFAULT_INTEGER(max_chat_history, DEF_MAX_CHAT_HISTORY);
|
||||
DEFAULT_INTEGER(max_logout_log, DEF_MAX_LOGOUT_LOG);
|
||||
@@ -191,11 +208,13 @@ void config_defaults(struct hub_config* config)
|
||||
DEFAULT_INTEGER(max_send_buffer, DEF_MAX_SEND_BUFFER);
|
||||
DEFAULT_INTEGER(max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
|
||||
DEFAULT_BOOLEAN(show_banner, DEF_SHOW_BANNER);
|
||||
DEFAULT_BOOLEAN(show_banner_sys_info, DEF_SHOW_BANNER_SYS_INFO);
|
||||
DEFAULT_BOOLEAN(obsolete_clients, DEF_OBSOLETE_CLIENTS);
|
||||
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);
|
||||
@@ -209,6 +228,14 @@ void config_defaults(struct hub_config* config)
|
||||
DEFAULT_INTEGER(limit_min_slots, DEF_LIMIT_MIN_SLOTS);
|
||||
DEFAULT_INTEGER(limit_max_slots, DEF_LIMIT_MAX_SLOTS);
|
||||
|
||||
/* Flood control */
|
||||
DEFAULT_INTEGER(flood_ctl_interval, DEF_FLOOD_INTERVAL);
|
||||
DEFAULT_INTEGER(flood_ctl_chat, DEF_FLOOD_CHAT);
|
||||
DEFAULT_INTEGER(flood_ctl_connect, DEF_FLOOD_CONNECT);
|
||||
DEFAULT_INTEGER(flood_ctl_search, DEF_FLOOD_SEARCH);
|
||||
DEFAULT_INTEGER(flood_ctl_update, DEF_FLOOD_UPDATE);
|
||||
DEFAULT_INTEGER(flood_ctl_extras, DEF_FLOOD_EXTRAS);
|
||||
|
||||
/* Status/error strings */
|
||||
DEFAULT_STRING (msg_hub_full, DEF_MSG_HUB_FULL);
|
||||
DEFAULT_STRING (msg_hub_disabled, DEF_MSG_HUB_DISABLED)
|
||||
@@ -239,6 +266,13 @@ void config_defaults(struct hub_config* config)
|
||||
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_STRING (msg_user_flood_chat, DEF_MSG_FLOOD_CHAT);
|
||||
DEFAULT_STRING (msg_user_flood_connect, DEF_MSG_FLOOD_CONNECT);
|
||||
DEFAULT_STRING (msg_user_flood_search, DEF_MSG_FLOOD_SEARCH);
|
||||
DEFAULT_STRING (msg_user_flood_update, DEF_MSG_FLOOD_UPDATE);
|
||||
DEFAULT_STRING (msg_user_flood_extras, DEF_MSG_FLOOD_EXTRAS);
|
||||
DEFAULT_STRING (msg_proto_no_common_hash, DEF_MSG_PROTO_NO_COMMON_HASH);
|
||||
DEFAULT_STRING (msg_proto_obsolete_adc0, DEF_MSG_PROTO_OBSOLETE_ADC0);
|
||||
|
||||
DEFAULT_INTEGER(tls_enable, DEF_TLS_ENABLE);
|
||||
DEFAULT_INTEGER(tls_require, DEF_TLS_REQUIRE);
|
||||
@@ -255,6 +289,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
||||
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);
|
||||
@@ -265,6 +300,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
||||
GET_INT (max_send_buffer);
|
||||
GET_INT (max_send_buffer_soft);
|
||||
GET_BOOL(show_banner);
|
||||
GET_BOOL(show_banner_sys_info);
|
||||
GET_BOOL(obsolete_clients);
|
||||
GET_BOOL(chat_only);
|
||||
GET_BOOL(chat_is_privileged);
|
||||
GET_BOOL(low_bandwidth_mode);
|
||||
@@ -282,7 +319,14 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
||||
GET_INT(limit_max_share);
|
||||
GET_INT(limit_min_slots);
|
||||
GET_INT(limit_max_slots);
|
||||
|
||||
|
||||
GET_INT(flood_ctl_interval);
|
||||
GET_INT(flood_ctl_chat);
|
||||
GET_INT(flood_ctl_connect);
|
||||
GET_INT(flood_ctl_search);
|
||||
GET_INT(flood_ctl_update);
|
||||
GET_INT(flood_ctl_extras);
|
||||
|
||||
/* Status/error strings */
|
||||
GET_STR (msg_hub_full);
|
||||
GET_STR (msg_hub_disabled);
|
||||
@@ -313,13 +357,21 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
||||
GET_STR (msg_user_slots_high);
|
||||
GET_STR (msg_user_hub_limit_low);
|
||||
GET_STR (msg_user_hub_limit_high);
|
||||
GET_STR (msg_user_flood_chat);
|
||||
GET_STR (msg_user_flood_connect);
|
||||
GET_STR (msg_user_flood_search);
|
||||
GET_STR (msg_user_flood_update);
|
||||
GET_STR (msg_user_flood_extras);
|
||||
GET_STR (msg_proto_no_common_hash);
|
||||
GET_STR (msg_proto_obsolete_adc0);
|
||||
|
||||
/* TLS/SSL related */
|
||||
GET_BOOL(tls_enable);
|
||||
GET_BOOL(tls_require);
|
||||
GET_STR (tls_certificate);
|
||||
GET_STR (tls_private_key);
|
||||
|
||||
/* Still here -- unknown directive */
|
||||
/* Still here -- unknown directive */
|
||||
LOG_ERROR("Unknown configuration directive: '%s'", key);
|
||||
return -1;
|
||||
}
|
||||
@@ -328,12 +380,13 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
||||
void free_config(struct hub_config* config)
|
||||
{
|
||||
hub_free(config->server_bind_addr);
|
||||
hub_free(config->server_alt_ports);
|
||||
hub_free(config->file_motd);
|
||||
hub_free(config->file_acl);
|
||||
hub_free(config->file_rules);
|
||||
hub_free(config->hub_name);
|
||||
hub_free(config->hub_description);
|
||||
|
||||
|
||||
hub_free(config->msg_hub_full);
|
||||
hub_free(config->msg_hub_disabled);
|
||||
hub_free(config->msg_hub_registered_users_only);
|
||||
@@ -363,7 +416,14 @@ void free_config(struct hub_config* config)
|
||||
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->msg_user_flood_chat);
|
||||
hub_free(config->msg_user_flood_connect);
|
||||
hub_free(config->msg_user_flood_search);
|
||||
hub_free(config->msg_user_flood_update);
|
||||
hub_free(config->msg_user_flood_extras);
|
||||
hub_free(config->msg_proto_no_common_hash);
|
||||
hub_free(config->msg_proto_obsolete_adc0);
|
||||
|
||||
hub_free(config->tls_certificate);
|
||||
hub_free(config->tls_private_key);
|
||||
|
||||
@@ -406,6 +466,7 @@ void dump_config(struct hub_config* config, int ignore_defaults)
|
||||
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);
|
||||
@@ -416,6 +477,8 @@ void dump_config(struct hub_config* config, int ignore_defaults)
|
||||
DUMP_INT (max_send_buffer, DEF_MAX_SEND_BUFFER);
|
||||
DUMP_INT (max_send_buffer_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(obsolete_clients, DEF_OBSOLETE_CLIENTS);
|
||||
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);
|
||||
@@ -440,7 +503,14 @@ void dump_config(struct hub_config* config, int ignore_defaults)
|
||||
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);
|
||||
|
||||
|
||||
DUMP_INT(flood_ctl_interval, DEF_FLOOD_INTERVAL);
|
||||
DUMP_INT(flood_ctl_chat, DEF_FLOOD_CHAT);
|
||||
DUMP_INT(flood_ctl_connect, DEF_FLOOD_CONNECT);
|
||||
DUMP_INT(flood_ctl_search, DEF_FLOOD_SEARCH);
|
||||
DUMP_INT(flood_ctl_update, DEF_FLOOD_UPDATE);
|
||||
DUMP_INT(flood_ctl_extras, DEF_FLOOD_EXTRAS);
|
||||
|
||||
/* Status/error strings */
|
||||
DUMP_STR (msg_hub_full, DEF_MSG_HUB_FULL);
|
||||
DUMP_STR (msg_hub_disabled, DEF_MSG_HUB_DISABLED);
|
||||
@@ -471,6 +541,13 @@ void dump_config(struct hub_config* config, int ignore_defaults)
|
||||
DUMP_STR (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
|
||||
DUMP_STR (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
|
||||
DUMP_STR (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
|
||||
DUMP_STR (msg_user_flood_chat, DEF_MSG_FLOOD_CHAT);
|
||||
DUMP_STR (msg_user_flood_connect, DEF_MSG_FLOOD_CONNECT);
|
||||
DUMP_STR (msg_user_flood_search, DEF_MSG_FLOOD_SEARCH);
|
||||
DUMP_STR (msg_user_flood_update, DEF_MSG_FLOOD_UPDATE);
|
||||
DUMP_STR (msg_user_flood_extras, DEF_MSG_FLOOD_EXTRAS);
|
||||
DUMP_STR (msg_proto_no_common_hash, DEF_MSG_PROTO_NO_COMMON_HASH);
|
||||
DUMP_STR (msg_proto_obsolete_adc0, DEF_MSG_PROTO_OBSOLETE_ADC0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -25,10 +25,13 @@ struct hub_config
|
||||
int server_port; /**<<< "Server port to bind to (default: 1511)" */
|
||||
char* server_bind_addr; /**<<< "Server bind address (default: '0.0.0.0' or '::')" */
|
||||
int server_listen_backlog; /**<<< "Server listen backlog (default: 50)" */
|
||||
char* server_alt_ports; /**<<< "Comma separated list of alternative ports to listen to (default: '')" */
|
||||
int hub_enabled; /**<<< "Is server enabled (default: 1)" */
|
||||
int show_banner; /**<<< "Show banner on connect (default: 1)" */
|
||||
int show_banner_sys_info; /**<<< "Show banner system information (default: 1). Has no effect unless show_banner is enabled." */
|
||||
int max_users; /**<<< "Maximum number of users allowed on the hub (default: 500)" */
|
||||
int registered_users_only; /**<<< "Allow registered users only (default: 0)" */
|
||||
int obsolete_clients; /**<<< "Support obsolete clients using a ADC protocol prior to 1.0 (default: off)" */
|
||||
int chat_only; /**<<< "Allow chat only operation on hub (default: 0)" */
|
||||
int chat_is_privileged; /**<<< "Allow chat for operators and above only (default: 0) */
|
||||
char* file_motd; /**<<< "File containing the 'message of the day' (default: '' - no motd)" */
|
||||
@@ -57,6 +60,13 @@ struct hub_config
|
||||
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)" */
|
||||
|
||||
int flood_ctl_interval; /**<<< "Time interval in seconds for flood control check. If 0 then all flood control is disabled. (0=off, default: 0)" */
|
||||
int flood_ctl_chat; /**<<< "Max chat messages allowed inside the time interval (0=off, default: 0)" */
|
||||
int flood_ctl_connect; /**<<< "Max connect requests allowed inside the time interval (0=off, default: 0)" */
|
||||
int flood_ctl_search; /**<<< "Max search requests allowed inside the time interval (0=off, default: 0)" */
|
||||
int flood_ctl_update; /**<<< "Max updates allowed inside the time interval (0=off, default: 0)" */
|
||||
int flood_ctl_extras; /**<<< "Max extra protocol messages allowed inside the time interval (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" */
|
||||
@@ -87,6 +97,13 @@ struct hub_config
|
||||
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." */
|
||||
|
||||
int tls_enable; /**<<< "Enable SSL/TLS support (default: 0)" */
|
||||
int tls_require; /**<<< "If SSL/TLS enabled, should it be required (default: 0) */
|
||||
|
||||
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 */
|
||||
|
||||
386
src/core/hub.c
386
src/core/hub.c
@@ -21,6 +21,31 @@
|
||||
|
||||
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 ret = 0;
|
||||
@@ -36,20 +61,32 @@ int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* lin
|
||||
{
|
||||
switch (cmd->cmd)
|
||||
{
|
||||
case ADC_CMD_HSUP: ret = hub_handle_support(hub, u, cmd); break;
|
||||
case ADC_CMD_HPAS: ret = hub_handle_password(hub, u, cmd); break;
|
||||
case ADC_CMD_BINF: ret = hub_handle_info(hub, u, cmd); break;
|
||||
case ADC_CMD_HSUP:
|
||||
CHECK_FLOOD(extras, 0);
|
||||
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_EINF:
|
||||
case ADC_CMD_FINF:
|
||||
/* these must never be allowed for security reasons,
|
||||
so we ignore them. */
|
||||
/* these must never be allowed for security reasons, so we ignore them. */
|
||||
break;
|
||||
|
||||
case ADC_CMD_EMSG:
|
||||
case ADC_CMD_DMSG:
|
||||
case ADC_CMD_BMSG:
|
||||
case ADC_CMD_FMSG:
|
||||
CHECK_FLOOD(chat, 1);
|
||||
ret = hub_handle_chat_message(hub, u, cmd);
|
||||
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_ESCH:
|
||||
case ADC_CMD_FSCH:
|
||||
cmd->priority = -1;
|
||||
CHECK_CHAT_ONLY;
|
||||
CHECK_FLOOD(search, 1);
|
||||
ROUTE_MSG;
|
||||
|
||||
case ADC_CMD_DRES:
|
||||
cmd->priority = -1;
|
||||
CHECK_CHAT_ONLY;
|
||||
/* CHECK_FLOOD(search, 0); */
|
||||
ROUTE_MSG;
|
||||
|
||||
case ADC_CMD_DRCM:
|
||||
case ADC_CMD_DCTM:
|
||||
cmd->priority = -1;
|
||||
if (hub->config->chat_only && u->credentials < cred_operator)
|
||||
{
|
||||
/* These below aren't allowed in chat only hubs */
|
||||
break;
|
||||
}
|
||||
CHECK_CHAT_ONLY;
|
||||
CHECK_FLOOD(connect, 1);
|
||||
ROUTE_MSG;
|
||||
|
||||
default:
|
||||
if (user_is_logged_in(u))
|
||||
{
|
||||
ret = route_message(hub, u, cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
CHECK_FLOOD(extras, 1);
|
||||
ROUTE_MSG;
|
||||
}
|
||||
adc_msg_free(cmd);
|
||||
}
|
||||
@@ -137,17 +175,46 @@ int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_mess
|
||||
if (u->state == state_protocol)
|
||||
{
|
||||
if (index == 0) ok = 0; /* Need to support *SOMETHING*, at least BASE */
|
||||
|
||||
if (ok)
|
||||
{
|
||||
hub_send_handshake(hub, u);
|
||||
net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
|
||||
}
|
||||
else
|
||||
if (!ok)
|
||||
{
|
||||
/* disconnect user. Do not send crap during initial handshake! */
|
||||
hub_disconnect_user(hub, u, quit_logon_error);
|
||||
ret = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (user_flag_get(u, feature_base))
|
||||
{
|
||||
/* User supports ADC/1.0 and a hash we know */
|
||||
if (user_flag_get(u, feature_tiger))
|
||||
{
|
||||
hub_send_handshake(hub, u);
|
||||
net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no common hash algorithm.
|
||||
hub_send_status(hub, u, status_msg_proto_no_common_hash, status_level_fatal);
|
||||
hub_disconnect_user(hub, u, quit_protocol_error);
|
||||
}
|
||||
}
|
||||
else if (user_flag_get(u, feature_bas0))
|
||||
{
|
||||
if (hub->config->obsolete_clients)
|
||||
{
|
||||
hub_send_handshake(hub, u);
|
||||
net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* disconnect user for using an obsolete client. */
|
||||
hub_send_status(hub, u, status_msg_proto_obsolete_adc0, status_level_fatal);
|
||||
hub_disconnect_user(hub, u, quit_protocol_error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Not speaking a compatible protocol - just disconnect. */
|
||||
hub_disconnect_user(hub, u, quit_logon_error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,6 +250,7 @@ int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc
|
||||
char* message = adc_msg_get_argument(cmd, 0);
|
||||
int ret = 0;
|
||||
int relay = 1;
|
||||
int offset;
|
||||
|
||||
if (!message || !user_is_logged_in(u))
|
||||
return 0;
|
||||
@@ -196,7 +264,7 @@ int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc
|
||||
if (message[1] == message[0])
|
||||
{
|
||||
relay = 1;
|
||||
int offset = adc_msg_get_arg_offset(cmd);
|
||||
offset = adc_msg_get_arg_offset(cmd);
|
||||
memmove(cmd->cache+offset+1, cmd->cache+offset+2, cmd->length - offset);
|
||||
cmd->length--;
|
||||
}
|
||||
@@ -392,6 +460,28 @@ void hub_send_password_challenge(struct hub_info* hub, struct hub_user* u)
|
||||
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)
|
||||
{
|
||||
struct hub_info* hub = (struct hub_info*) callback_data;
|
||||
@@ -496,6 +586,101 @@ static struct net_connection* start_listening_socket(const char* bind_addr, uint
|
||||
return server;
|
||||
}
|
||||
|
||||
struct server_alt_port_data
|
||||
{
|
||||
struct hub_info* hub;
|
||||
struct hub_config* config;
|
||||
};
|
||||
|
||||
static int server_alt_port_start_one(char* line, int count, void* ptr)
|
||||
{
|
||||
struct server_alt_port_data* data = (struct server_alt_port_data*) ptr;
|
||||
|
||||
int port = uhub_atoi(line);
|
||||
struct net_connection* con = start_listening_socket(data->config->server_bind_addr, port, data->config->server_listen_backlog, data->hub);
|
||||
if (con)
|
||||
{
|
||||
list_append(data->hub->server_alt_ports, con);
|
||||
LOG_INFO("Listening on alternate port %d...", port);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void server_alt_port_start(struct hub_info* hub, struct hub_config* config)
|
||||
{
|
||||
struct server_alt_port_data data;
|
||||
|
||||
if (!config->server_alt_ports || !*config->server_alt_ports)
|
||||
return;
|
||||
|
||||
hub->server_alt_ports = (struct linked_list*) list_create();
|
||||
|
||||
data.hub = hub;
|
||||
data.config = config;
|
||||
|
||||
string_split(config->server_alt_ports, ",", &data, server_alt_port_start_one);
|
||||
}
|
||||
|
||||
static void server_alt_port_clear(void* ptr)
|
||||
{
|
||||
struct net_connection* con = (struct net_connection*) ptr;
|
||||
if (con)
|
||||
{
|
||||
net_con_close(con);
|
||||
hub_free(con);
|
||||
}
|
||||
}
|
||||
|
||||
static void server_alt_port_stop(struct hub_info* hub)
|
||||
{
|
||||
if (hub->server_alt_ports)
|
||||
{
|
||||
list_clear(hub->server_alt_ports, &server_alt_port_clear);
|
||||
list_destroy(hub->server_alt_ports);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
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 = 0;
|
||||
@@ -525,30 +710,10 @@ 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);
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
if (config->tls_enable)
|
||||
if (!load_ssl_certificates(hub, config))
|
||||
{
|
||||
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);
|
||||
hub_free(hub);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -596,6 +761,8 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
||||
return 0;
|
||||
}
|
||||
|
||||
server_alt_port_start(hub, config);
|
||||
|
||||
hub->status = hub_status_running;
|
||||
|
||||
g_hub = hub;
|
||||
@@ -607,9 +774,14 @@ void hub_shutdown_service(struct hub_info* hub)
|
||||
{
|
||||
LOG_DEBUG("hub_shutdown_service()");
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
unload_ssl_certificates(hub);
|
||||
#endif
|
||||
|
||||
event_queue_shutdown(hub->queue);
|
||||
net_con_close(hub->server);
|
||||
hub_free(hub->server);
|
||||
server_alt_port_stop(hub);
|
||||
uman_shutdown(hub);
|
||||
hub->status = hub_status_stopped;
|
||||
hub_free(hub->sendbuf);
|
||||
@@ -623,17 +795,15 @@ void hub_shutdown_service(struct hub_info* hub)
|
||||
g_hub = 0;
|
||||
}
|
||||
|
||||
#define SERVER "" PRODUCT "/" VERSION ""
|
||||
|
||||
void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
||||
{
|
||||
int fd, ret;
|
||||
char buf[MAX_RECV_BUF];
|
||||
char* tmp;
|
||||
char* server = adc_msg_escape(SERVER); /* FIXME: OOM */
|
||||
char* server = adc_msg_escape(PRODUCT_STRING); /* FIXME: OOM */
|
||||
|
||||
hub->acl = acl;
|
||||
hub->command_info = adc_msg_construct(ADC_CMD_IINF, 15 + strlen(server));
|
||||
hub->command_info = adc_msg_construct(ADC_CMD_IINF, 15);
|
||||
if (hub->command_info)
|
||||
{
|
||||
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_CLIENT_TYPE, ADC_CLIENT_TYPE_HUB);
|
||||
@@ -687,10 +857,13 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
||||
adc_msg_add_argument(hub->command_support, ADC_PROTO_SUPPORT);
|
||||
}
|
||||
|
||||
hub->command_banner = adc_msg_construct(ADC_CMD_ISTA, 25 + strlen(server));
|
||||
hub->command_banner = adc_msg_construct(ADC_CMD_ISTA, 100 + strlen(server));
|
||||
if (hub->command_banner)
|
||||
{
|
||||
tmp = adc_msg_escape("Powered by " SERVER);
|
||||
if (hub->config->show_banner_sys_info)
|
||||
tmp = adc_msg_escape("Powered by " PRODUCT_STRING " on " OPSYS "/" CPUINFO);
|
||||
else
|
||||
tmp = adc_msg_escape("Powered by " PRODUCT_STRING);
|
||||
adc_msg_add_argument(hub->command_banner, "000");
|
||||
adc_msg_add_argument(hub->command_banner, tmp);
|
||||
hub_free(tmp);
|
||||
@@ -764,62 +937,81 @@ void hub_send_status(struct hub_info* hub, struct hub_user* user, enum status_me
|
||||
{
|
||||
struct hub_config* cfg = hub->config;
|
||||
struct adc_message* cmd = adc_msg_construct(ADC_CMD_ISTA, 6);
|
||||
if (!cmd) return;
|
||||
struct adc_message* qui = adc_msg_construct(ADC_CMD_IQUI, 256);
|
||||
char code[4];
|
||||
char buf[250];
|
||||
const char* text = 0;
|
||||
const char* flag = 0;
|
||||
char* escaped_text = 0;
|
||||
|
||||
#define STATUS(CODE, MSG, FLAG) case status_ ## MSG : set_status_code(level, CODE, code); text = cfg->MSG; flag = FLAG; break
|
||||
int reconnect_time = 0;
|
||||
|
||||
if (!cmd) return;
|
||||
|
||||
#define STATUS(CODE, MSG, FLAG, RCONTIME) case status_ ## MSG : set_status_code(level, CODE, code); text = cfg->MSG; flag = FLAG; reconnect_time = RCONTIME; break
|
||||
switch (msg)
|
||||
{
|
||||
STATUS(11, msg_hub_full, 0);
|
||||
STATUS(12, msg_hub_disabled, 0);
|
||||
STATUS(26, msg_hub_registered_users_only, 0);
|
||||
STATUS(43, msg_inf_error_nick_missing, 0);
|
||||
STATUS(43, msg_inf_error_nick_multiple, 0);
|
||||
STATUS(21, msg_inf_error_nick_invalid, 0);
|
||||
STATUS(21, msg_inf_error_nick_long, 0);
|
||||
STATUS(21, msg_inf_error_nick_short, 0);
|
||||
STATUS(21, msg_inf_error_nick_spaces, 0);
|
||||
STATUS(21, msg_inf_error_nick_bad_chars, 0);
|
||||
STATUS(21, msg_inf_error_nick_not_utf8, 0);
|
||||
STATUS(22, msg_inf_error_nick_taken, 0);
|
||||
STATUS(21, msg_inf_error_nick_restricted, 0);
|
||||
STATUS(43, msg_inf_error_cid_invalid, "FBID");
|
||||
STATUS(43, msg_inf_error_cid_missing, "FMID");
|
||||
STATUS(24, msg_inf_error_cid_taken, 0);
|
||||
STATUS(43, msg_inf_error_pid_missing, "FMPD");
|
||||
STATUS(27, msg_inf_error_pid_invalid, "FBPD");
|
||||
STATUS(31, msg_ban_permanently, 0);
|
||||
STATUS(32, msg_ban_temporarily, "TL600"); /* FIXME: Use a proper timeout */
|
||||
STATUS(23, msg_auth_invalid_password, 0);
|
||||
STATUS(20, msg_auth_user_not_found, 0);
|
||||
STATUS(30, msg_error_no_memory, 0);
|
||||
STATUS(43, msg_user_share_size_low, "FB" ADC_INF_FLAG_SHARED_SIZE);
|
||||
STATUS(43, msg_user_share_size_high, "FB" ADC_INF_FLAG_SHARED_SIZE);
|
||||
STATUS(43, msg_user_slots_low, "FB" ADC_INF_FLAG_UPLOAD_SLOTS);
|
||||
STATUS(43, msg_user_slots_high, "FB" ADC_INF_FLAG_UPLOAD_SLOTS);
|
||||
STATUS(43, msg_user_hub_limit_low, 0);
|
||||
STATUS(43, msg_user_hub_limit_high, 0);
|
||||
STATUS(11, msg_hub_full, 0, 600); /* FIXME: Proper timeout? */
|
||||
STATUS(12, msg_hub_disabled, 0, -1);
|
||||
STATUS(26, msg_hub_registered_users_only, 0, 0);
|
||||
STATUS(43, msg_inf_error_nick_missing, 0, 0);
|
||||
STATUS(43, msg_inf_error_nick_multiple, 0, 0);
|
||||
STATUS(21, msg_inf_error_nick_invalid, 0, 0);
|
||||
STATUS(21, msg_inf_error_nick_long, 0, 0);
|
||||
STATUS(21, msg_inf_error_nick_short, 0, 0);
|
||||
STATUS(21, msg_inf_error_nick_spaces, 0, 0);
|
||||
STATUS(21, msg_inf_error_nick_bad_chars, 0, 0);
|
||||
STATUS(21, msg_inf_error_nick_not_utf8, 0, 0);
|
||||
STATUS(22, msg_inf_error_nick_taken, 0, 0);
|
||||
STATUS(21, msg_inf_error_nick_restricted, 0, 0);
|
||||
STATUS(43, msg_inf_error_cid_invalid, "FBID", 0);
|
||||
STATUS(43, msg_inf_error_cid_missing, "FMID", 0);
|
||||
STATUS(24, msg_inf_error_cid_taken, 0, 0);
|
||||
STATUS(43, msg_inf_error_pid_missing, "FMPD", 0);
|
||||
STATUS(27, msg_inf_error_pid_invalid, "FBPD", 0);
|
||||
STATUS(31, msg_ban_permanently, 0, 0);
|
||||
STATUS(32, msg_ban_temporarily, "TL600", 600); /* FIXME: Proper timeout? */
|
||||
STATUS(23, msg_auth_invalid_password, 0, 0);
|
||||
STATUS(20, msg_auth_user_not_found, 0, 0);
|
||||
STATUS(30, msg_error_no_memory, 0, 0);
|
||||
STATUS(43, msg_user_share_size_low, "FB" ADC_INF_FLAG_SHARED_SIZE, 0);
|
||||
STATUS(43, msg_user_share_size_high, "FB" ADC_INF_FLAG_SHARED_SIZE, 0);
|
||||
STATUS(43, msg_user_slots_low, "FB" ADC_INF_FLAG_UPLOAD_SLOTS, 0);
|
||||
STATUS(43, msg_user_slots_high, "FB" ADC_INF_FLAG_UPLOAD_SLOTS, 0);
|
||||
STATUS(43, msg_user_hub_limit_low, 0, 0);
|
||||
STATUS(43, msg_user_hub_limit_high, 0, 0);
|
||||
STATUS(47, msg_proto_no_common_hash, 0, -1);
|
||||
STATUS(40, msg_proto_obsolete_adc0, 0, -1);
|
||||
}
|
||||
#undef STATUS
|
||||
|
||||
escaped_text = adc_msg_escape(text);
|
||||
|
||||
|
||||
adc_msg_add_argument(cmd, code);
|
||||
adc_msg_add_argument(cmd, escaped_text);
|
||||
|
||||
hub_free(escaped_text);
|
||||
|
||||
|
||||
if (flag)
|
||||
{
|
||||
adc_msg_add_argument(cmd, flag);
|
||||
}
|
||||
|
||||
|
||||
route_to_user(hub, user, cmd);
|
||||
|
||||
if (level >= status_level_fatal)
|
||||
{
|
||||
snprintf(buf, 230, "MS%s", escaped_text);
|
||||
adc_msg_add_argument(qui, buf);
|
||||
|
||||
if (reconnect_time != 0)
|
||||
{
|
||||
snprintf(buf, 10, "TL%d", reconnect_time);
|
||||
adc_msg_add_argument(qui, buf);
|
||||
}
|
||||
route_to_user(hub, user, qui);
|
||||
}
|
||||
|
||||
hub_free(escaped_text);
|
||||
adc_msg_free(cmd);
|
||||
|
||||
adc_msg_free(qui);
|
||||
}
|
||||
|
||||
const char* hub_get_status_message(struct hub_info* hub, enum status_message msg)
|
||||
@@ -857,6 +1049,8 @@ const char* hub_get_status_message(struct hub_info* hub, enum status_message msg
|
||||
STATUS(msg_user_slots_high);
|
||||
STATUS(msg_user_hub_limit_low);
|
||||
STATUS(msg_user_hub_limit_high);
|
||||
STATUS(msg_proto_no_common_hash);
|
||||
STATUS(msg_proto_obsolete_adc0);
|
||||
}
|
||||
#undef STATUS
|
||||
return "Unknown";
|
||||
@@ -896,6 +1090,8 @@ const char* hub_get_status_message_log(struct hub_info* hub, enum status_message
|
||||
STATUS(msg_user_slots_high);
|
||||
STATUS(msg_user_hub_limit_low);
|
||||
STATUS(msg_user_hub_limit_high);
|
||||
STATUS(msg_proto_no_common_hash);
|
||||
STATUS(msg_proto_obsolete_adc0);
|
||||
}
|
||||
#undef STATUS
|
||||
return "unknown";
|
||||
|
||||
@@ -45,7 +45,7 @@ enum status_message
|
||||
status_msg_auth_invalid_password = -21, /* Password is wrong */
|
||||
status_msg_auth_user_not_found = -22, /* User not found in password database */
|
||||
status_msg_error_no_memory = -23, /* Hub is out of memory */
|
||||
|
||||
|
||||
status_msg_user_share_size_low = -40, /* User is not sharing enough. */
|
||||
status_msg_user_share_size_high = -41, /* User is sharing too much. */
|
||||
status_msg_user_slots_low = -42, /* User has too few slots open. */
|
||||
@@ -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_high = -45, /* Use is on too many hubs. */
|
||||
|
||||
status_msg_proto_no_common_hash = -50, /* No common hash algorithms */
|
||||
status_msg_proto_obsolete_adc0 = -51, /* Client is using an obsolete protocol version */
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -91,6 +95,7 @@ struct hub_logout_info
|
||||
struct hub_info
|
||||
{
|
||||
struct net_connection* server;
|
||||
struct linked_list* server_alt_ports;
|
||||
struct hub_stats stats;
|
||||
struct event_queue* queue;
|
||||
struct hub_config* config;
|
||||
@@ -222,6 +227,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);
|
||||
|
||||
/**
|
||||
* 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,
|
||||
* and returns a hub handle.
|
||||
|
||||
@@ -33,6 +33,13 @@ static void log_user_login_error(struct hub_user* u, enum status_message msg)
|
||||
LOG_USER("LoginError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent);
|
||||
}
|
||||
|
||||
static void log_user_update_error(struct hub_user* u, enum status_message msg)
|
||||
{
|
||||
const char* addr = user_get_address(u);
|
||||
const char* message = hub_get_status_message_log(u->hub, msg);
|
||||
LOG_USER("UpdateError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent);
|
||||
}
|
||||
|
||||
static void log_user_logout(struct hub_user* u, const char* message)
|
||||
{
|
||||
const char* addr = user_get_address(u);
|
||||
@@ -83,6 +90,13 @@ void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_mess
|
||||
hub_disconnect_user(hub, u, quit_logon_error);
|
||||
}
|
||||
|
||||
void on_update_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg)
|
||||
{
|
||||
log_user_update_error(u, msg);
|
||||
hub_send_status(hub, u, msg, status_level_fatal);
|
||||
hub_disconnect_user(hub, u, quit_update_error);
|
||||
}
|
||||
|
||||
void on_nick_change(struct hub_info* hub, struct hub_user* u, const char* nick)
|
||||
{
|
||||
if (user_is_logged_in(u))
|
||||
|
||||
@@ -29,6 +29,7 @@ extern void on_login_success(struct hub_info* hub, struct hub_user* u);
|
||||
* This event is triggered whenever a user failed to log in to the hub.
|
||||
*/
|
||||
extern void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg);
|
||||
extern void on_update_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg);
|
||||
|
||||
/**
|
||||
* This event is triggered whenever a previously logged in user leaves the hub.
|
||||
|
||||
@@ -126,6 +126,7 @@ void hub_sendq_add(struct hub_sendq* q, struct adc_message* msg_)
|
||||
#ifdef DEBUG_SENDQ
|
||||
debug_msg("hub_sendq_add", msg);
|
||||
#endif
|
||||
assert(msg->cache && *msg->cache);
|
||||
list_append(q->queue, msg);
|
||||
q->size += msg->length;
|
||||
}
|
||||
@@ -143,10 +144,11 @@ void hub_sendq_remove(struct hub_sendq* q, struct adc_message* msg)
|
||||
|
||||
int hub_sendq_send(struct hub_sendq* q, struct hub_user* user)
|
||||
{
|
||||
int ret;
|
||||
struct adc_message* msg = list_get_first(q->queue);
|
||||
if (!msg) return 0;
|
||||
|
||||
int ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
|
||||
assert(msg->cache && *msg->cache);
|
||||
ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
|
||||
|
||||
if (ret > 0)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -42,7 +42,7 @@ static void remove_server_restricted_flags(struct adc_message* cmd)
|
||||
static int set_feature_cast_supports(struct hub_user* u, struct adc_message* cmd)
|
||||
{
|
||||
char *it, *tmp;
|
||||
|
||||
|
||||
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_SUPPORT))
|
||||
{
|
||||
tmp = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SUPPORT);
|
||||
@@ -58,7 +58,7 @@ static int set_feature_cast_supports(struct hub_user* u, struct adc_message* cmd
|
||||
user_set_feature_cast_support(u, it);
|
||||
it = &it[5];
|
||||
}
|
||||
|
||||
|
||||
if (*it)
|
||||
{
|
||||
user_set_feature_cast_support(u, it);
|
||||
@@ -74,9 +74,9 @@ static int check_hash_tiger(const char* cid, const char* pid)
|
||||
char x_pid[64];
|
||||
char raw_pid[64];
|
||||
uint64_t tiger_res[3];
|
||||
|
||||
|
||||
memset(x_pid, 0, MAX_CID_LEN+1);
|
||||
|
||||
|
||||
base32_decode(pid, (unsigned char*) raw_pid, MAX_CID_LEN);
|
||||
tiger((uint64_t*) raw_pid, TIGERSIZE, (uint64_t*) tiger_res);
|
||||
base32_encode((unsigned char*) tiger_res, TIGERSIZE, x_pid);
|
||||
@@ -102,7 +102,7 @@ static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_mes
|
||||
hub_free(pid);
|
||||
return status_msg_error_no_memory;
|
||||
}
|
||||
|
||||
|
||||
if (strlen(cid) != MAX_CID_LEN)
|
||||
{
|
||||
hub_free(cid);
|
||||
@@ -125,7 +125,7 @@ static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_mes
|
||||
hub_free(pid);
|
||||
return status_msg_inf_error_cid_invalid;
|
||||
}
|
||||
|
||||
|
||||
if (!is_valid_base32_char(pid[pos]))
|
||||
{
|
||||
hub_free(cid);
|
||||
@@ -187,7 +187,7 @@ static int check_required_login_flags(struct hub_info* hub, struct hub_user* use
|
||||
* remove any wrong address, and replace it with the correct one
|
||||
* as seen by the hub.
|
||||
*/
|
||||
int check_network(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||
static int check_network(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
const char* address = user_get_address(user);
|
||||
|
||||
@@ -223,7 +223,7 @@ int check_network(struct hub_info* hub, struct hub_user* user, struct adc_messag
|
||||
return 0;
|
||||
}
|
||||
|
||||
void strip_network(struct hub_user* user, struct adc_message* cmd)
|
||||
static void strip_network(struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT);
|
||||
@@ -415,7 +415,7 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
|
||||
int64_t shared_size = atoll(arg);
|
||||
if (shared_size < 0)
|
||||
shared_size = 0;
|
||||
|
||||
|
||||
if (user_is_logged_in(user))
|
||||
{
|
||||
hub->users->shared_size -= user->limits.shared_size;
|
||||
@@ -425,14 +425,14 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
|
||||
hub_free(arg);
|
||||
arg = 0;
|
||||
}
|
||||
|
||||
|
||||
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES);
|
||||
if (arg)
|
||||
{
|
||||
ssize_t shared_files = atoll(arg);
|
||||
if (shared_files < 0)
|
||||
shared_files = 0;
|
||||
|
||||
|
||||
if (user_is_logged_in(user))
|
||||
{
|
||||
hub->users->shared_files -= user->limits.shared_files;
|
||||
@@ -442,7 +442,7 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
|
||||
hub_free(arg);
|
||||
arg = 0;
|
||||
}
|
||||
|
||||
|
||||
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_NORMAL);
|
||||
if (arg)
|
||||
{
|
||||
@@ -497,7 +497,7 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
|
||||
{
|
||||
return status_msg_user_share_size_high;
|
||||
}
|
||||
|
||||
|
||||
if ((user->limits.hub_count_user > hub_get_max_hubs_user(hub) && hub_get_max_hubs_user(hub)) ||
|
||||
(user->limits.hub_count_registered > hub_get_max_hubs_reg(hub) && hub_get_max_hubs_reg(hub)) ||
|
||||
(user->limits.hub_count_operator > hub_get_max_hubs_op(hub) && hub_get_max_hubs_op(hub)) ||
|
||||
@@ -505,14 +505,14 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
|
||||
{
|
||||
return status_msg_user_hub_limit_high;
|
||||
}
|
||||
|
||||
|
||||
if ((user->limits.hub_count_user < hub_get_min_hubs_user(hub) && hub_get_min_hubs_user(hub)) ||
|
||||
(user->limits.hub_count_registered < hub_get_min_hubs_reg(hub) && hub_get_min_hubs_reg(hub)) ||
|
||||
(user->limits.hub_count_operator < hub_get_min_hubs_op(hub) && hub_get_min_hubs_op(hub)))
|
||||
{
|
||||
return status_msg_user_hub_limit_low;
|
||||
}
|
||||
|
||||
|
||||
if (user->limits.upload_slots < hub_get_min_slots(hub) && hub_get_min_slots(hub))
|
||||
{
|
||||
return status_msg_user_slots_low;
|
||||
@@ -526,7 +526,6 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the expected credentials, and returns 1 if authentication is needed,
|
||||
* or 0 if not.
|
||||
@@ -560,11 +559,11 @@ static int set_credentials(struct hub_info* hub, struct hub_user* user, struct a
|
||||
case cred_guest:
|
||||
/* Nothing to be added to the info message */
|
||||
break;
|
||||
|
||||
|
||||
case cred_user:
|
||||
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_REGISTERED_USER);
|
||||
break;
|
||||
|
||||
|
||||
case cred_operator:
|
||||
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_OPERATOR);
|
||||
break;
|
||||
@@ -572,11 +571,11 @@ static int set_credentials(struct hub_info* hub, struct hub_user* user, struct a
|
||||
case cred_super:
|
||||
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_SUPER_USER);
|
||||
break;
|
||||
|
||||
|
||||
case cred_admin:
|
||||
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_ADMIN);
|
||||
break;
|
||||
|
||||
|
||||
case cred_link:
|
||||
break;
|
||||
}
|
||||
@@ -648,7 +647,7 @@ static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct hub_user*
|
||||
return ret; \
|
||||
} while(0)
|
||||
|
||||
int hub_perform_login_checks(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||
static int hub_perform_login_checks(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
/* Make syntax checks. */
|
||||
INF_CHECK(check_required_login_flags, hub, user, cmd);
|
||||
@@ -671,13 +670,12 @@ int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct ad
|
||||
int code = 0;
|
||||
|
||||
INF_CHECK(hub_perform_login_checks, hub, user, cmd);
|
||||
|
||||
|
||||
/* Private ID must never be broadcasted - drop it! */
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
|
||||
|
||||
|
||||
|
||||
code = set_credentials(hub, user, cmd);
|
||||
|
||||
|
||||
/* Note: this must be done *after* set_credentials. */
|
||||
if (check_is_hub_full(hub, user))
|
||||
{
|
||||
@@ -715,6 +713,7 @@ int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct ad
|
||||
*/
|
||||
int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct adc_message* cmd_unmodified)
|
||||
{
|
||||
int ret;
|
||||
struct adc_message* cmd = adc_msg_copy(cmd_unmodified);
|
||||
if (!cmd) return -1; /* OOM */
|
||||
|
||||
@@ -736,8 +735,8 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
|
||||
adc_msg_free(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = hub_handle_info_login(hub, user, cmd);
|
||||
|
||||
ret = hub_handle_info_login(hub, user, cmd);
|
||||
if (ret < 0)
|
||||
{
|
||||
on_login_failure(hub, user, ret);
|
||||
@@ -762,7 +761,7 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
|
||||
/* These must not be allowed updated, let's remove them! */
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID);
|
||||
|
||||
|
||||
/*
|
||||
* If the nick is not accepted, do not relay it.
|
||||
* Otherwise, the nickname will be updated.
|
||||
@@ -774,21 +773,29 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
|
||||
#endif
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK);
|
||||
}
|
||||
|
||||
/* FIXME - What if limits are not met ? */
|
||||
check_limits(hub, user, cmd);
|
||||
|
||||
ret = check_limits(hub, user, cmd);
|
||||
if (ret < 0)
|
||||
{
|
||||
on_update_failure(hub, user, ret);
|
||||
adc_msg_free(cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strip_network(user, cmd);
|
||||
hub_handle_info_low_bandwidth(hub, user, cmd);
|
||||
|
||||
|
||||
user_update_info(user, cmd);
|
||||
|
||||
|
||||
if (!adc_msg_is_empty(cmd))
|
||||
{
|
||||
route_message(hub, user, cmd);
|
||||
}
|
||||
|
||||
|
||||
adc_msg_free(cmd);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -77,12 +77,14 @@ static int signals[] =
|
||||
void setup_signal_handlers(struct hub_info* hub)
|
||||
{
|
||||
sigset_t sig_set;
|
||||
sigemptyset(&sig_set);
|
||||
struct sigaction act;
|
||||
int i;
|
||||
|
||||
sigemptyset(&sig_set);
|
||||
act.sa_mask = sig_set;
|
||||
act.sa_flags = SA_ONSTACK | SA_RESTART;
|
||||
act.sa_flags = SA_ONSTACK | SA_RESTART;
|
||||
act.sa_handler = hub_handle_signal;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; signals[i]; i++)
|
||||
{
|
||||
if (sigaction(signals[i], &act, 0) != 0)
|
||||
@@ -188,8 +190,8 @@ int check_configuration(int dump)
|
||||
|
||||
void print_version()
|
||||
{
|
||||
fprintf(stdout, "" PRODUCT " " VERSION "\n");
|
||||
fprintf(stdout, "Copyright (C) 2007-2009, Jan Vidar Krey <janvidar@extatic.org>\n"
|
||||
fprintf(stdout, PRODUCT_STRING "\n");
|
||||
fprintf(stdout, COPYRIGHT "\n"
|
||||
"This is free software with ABSOLUTELY NO WARRANTY.\n\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -24,41 +24,16 @@
|
||||
/* FIXME: This should not be needed! */
|
||||
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)
|
||||
{
|
||||
static char buf[MAX_RECV_BUF];
|
||||
struct hub_recvq* q = user->recv_queue;
|
||||
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)
|
||||
buf_size += size;
|
||||
@@ -219,7 +194,7 @@ void net_on_accept(struct net_connection* con, int event, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
addr = ip_convert_to_string(&ipaddr);
|
||||
addr = ip_convert_to_string(&ipaddr);
|
||||
|
||||
/* FIXME: Should have a plugin log this */
|
||||
LOG_TRACE("Got connection from %s", addr);
|
||||
@@ -228,7 +203,7 @@ void net_on_accept(struct net_connection* con, int event, void *arg)
|
||||
if (acl_is_ip_banned(hub->acl, addr))
|
||||
{
|
||||
LOG_INFO("Denied [%s] (IP banned)", addr);
|
||||
net_con_close(con);
|
||||
net_close(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -236,7 +211,7 @@ void net_on_accept(struct net_connection* con, int event, void *arg)
|
||||
if (!probe)
|
||||
{
|
||||
LOG_ERROR("Unable to create probe after socket accepted. Out of memory?");
|
||||
net_con_close(con);
|
||||
net_close(fd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,13 @@ static void probe_net_event(struct net_connection* con, int events, void *arg)
|
||||
if (memcmp(probe_recvbuf, "HSUP", 4) == 0)
|
||||
{
|
||||
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))
|
||||
{
|
||||
probe->connection = 0;
|
||||
|
||||
@@ -106,6 +106,8 @@ int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_messag
|
||||
if (!user->connection)
|
||||
return 0;
|
||||
|
||||
assert(msg->cache && *msg->cache);
|
||||
|
||||
if (hub_sendq_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline))
|
||||
{
|
||||
/* 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));
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -83,7 +89,14 @@ void user_set_state(struct hub_user* user, enum user_state state)
|
||||
void user_set_info(struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
adc_msg_free(user->info);
|
||||
user->info = adc_msg_incref(cmd);
|
||||
if (cmd)
|
||||
{
|
||||
user->info = adc_msg_incref(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
user->info = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void user_update_info(struct hub_user* u, struct adc_message* cmd)
|
||||
@@ -97,7 +110,7 @@ void user_update_info(struct hub_user* u, struct adc_message* cmd)
|
||||
/* FIXME: OOM! */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FIXME: Optimization potential:
|
||||
*
|
||||
@@ -127,10 +140,9 @@ static int convert_support_fourcc(int fourcc)
|
||||
{
|
||||
switch (fourcc)
|
||||
{
|
||||
case FOURCC('B','A','S','0'): /* Obsolete */
|
||||
#ifndef OLD_ADC_SUPPORT
|
||||
return 0;
|
||||
#endif
|
||||
case FOURCC('B','A','S','0'):
|
||||
return feature_bas0;
|
||||
|
||||
case FOURCC('B','A','S','E'):
|
||||
return feature_base;
|
||||
|
||||
@@ -336,6 +348,7 @@ const char* user_get_quit_reason_string(enum user_quit_reason reason)
|
||||
case quit_socket_error: return "socket error"; break;
|
||||
case quit_protocol_error: return "protocol error"; break;
|
||||
case quit_logon_error: return "login error"; break;
|
||||
case quit_update_error: return "update error"; break;
|
||||
case quit_hub_disabled: return "hub disabled"; break;
|
||||
case quit_ghost_timeout: return "ghost"; break;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
struct hub_info;
|
||||
struct hub_iobuf;
|
||||
struct flood_control;
|
||||
|
||||
enum user_state
|
||||
{
|
||||
@@ -45,6 +46,8 @@ enum user_flags
|
||||
feature_ping = 0x00000080, /** PING: Hub pinger information extension */
|
||||
feature_link = 0x00000100, /** LINK: Hub link (not supported) */
|
||||
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_ignore = 0x01000000, /** Ignore further reads */
|
||||
flag_maxbuf = 0x02000000, /** Hit max buf read, ignore msg */
|
||||
@@ -68,8 +71,9 @@ enum user_quit_reason
|
||||
quit_socket_error = 7, /** A socket error occured */
|
||||
quit_protocol_error = 8, /** Fatal protocol error */
|
||||
quit_logon_error = 9, /** Unable to login (wrong password, CID/PID, etc) */
|
||||
quit_hub_disabled = 10, /** Hub is disabled. No new connections allowed */
|
||||
quit_ghost_timeout = 11, /** The user is a ghost, and trying to login from another connection */
|
||||
quit_update_error = 10, /** Update error. INF update changed share/slot info and no longer satisfies the hub limits. */
|
||||
quit_hub_disabled = 11, /** Hub is disabled. No new connections allowed */
|
||||
quit_ghost_timeout = 12, /** The user is a ghost, and trying to login from another connection */
|
||||
};
|
||||
|
||||
/** Returns an apropriate string for the given quit reason */
|
||||
@@ -115,6 +119,11 @@ struct hub_user
|
||||
struct hub_user_limits limits; /** Data used for limitation */
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -93,9 +93,12 @@ int uman_init(struct hub_info* hub)
|
||||
return -1;
|
||||
}
|
||||
|
||||
users->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
|
||||
timeout_evt_initialize(users->timeout, timer_statistics, hub);
|
||||
timeout_queue_insert(net_backend_get_timeout_queue(), users->timeout, TIMEOUT_STATS);
|
||||
if (net_backend_get_timeout_queue())
|
||||
{
|
||||
users->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
|
||||
timeout_evt_initialize(users->timeout, timer_statistics, hub);
|
||||
timeout_queue_insert(net_backend_get_timeout_queue(), users->timeout, TIMEOUT_STATS);
|
||||
}
|
||||
|
||||
hub->users = users;
|
||||
return 0;
|
||||
@@ -107,8 +110,11 @@ int uman_shutdown(struct hub_info* hub)
|
||||
if (!hub || !hub->users)
|
||||
return -1;
|
||||
|
||||
timeout_queue_remove(net_backend_get_timeout_queue(), hub->users->timeout);
|
||||
hub_free(hub->users->timeout);
|
||||
if (net_backend_get_timeout_queue())
|
||||
{
|
||||
timeout_queue_remove(net_backend_get_timeout_queue(), hub->users->timeout);
|
||||
hub_free(hub->users->timeout);
|
||||
}
|
||||
|
||||
if (hub->users->list)
|
||||
{
|
||||
@@ -149,7 +155,7 @@ int uman_remove(struct hub_info* hub, struct hub_user* user)
|
||||
return -1;
|
||||
|
||||
list_remove(hub->users->list, user);
|
||||
|
||||
|
||||
if (hub->users->count > 0)
|
||||
{
|
||||
hub->users->count--;
|
||||
@@ -158,12 +164,12 @@ int uman_remove(struct hub_info* hub, struct hub_user* user)
|
||||
{
|
||||
assert(!"negative count!");
|
||||
}
|
||||
|
||||
|
||||
hub->users->shared_size -= user->limits.shared_size;
|
||||
hub->users->shared_files -= user->limits.shared_files;
|
||||
|
||||
user->hub = 0;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -218,8 +224,9 @@ size_t uman_get_user_by_addr(struct hub_info* hub, struct linked_list* users, st
|
||||
int uman_send_user_list(struct hub_info* hub, struct hub_user* target)
|
||||
{
|
||||
int ret = 1;
|
||||
struct hub_user* user;
|
||||
user_flag_set(target, flag_user_list);
|
||||
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on INF or PAS msg */
|
||||
user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on INF or PAS msg */
|
||||
while (user)
|
||||
{
|
||||
if (user_is_logged_in(user))
|
||||
@@ -230,7 +237,7 @@ int uman_send_user_list(struct hub_info* hub, struct hub_user* target)
|
||||
}
|
||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
FIXME: FIXME FIXME handle send queue excess
|
||||
if (!target->send_queue_size)
|
||||
@@ -241,12 +248,11 @@ int uman_send_user_list(struct hub_info* hub, struct hub_user* target)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void uman_send_quit_message(struct hub_info* hub, struct hub_user* leaving)
|
||||
{
|
||||
struct adc_message* command = adc_msg_construct(ADC_CMD_IQUI, 6);
|
||||
adc_msg_add_argument(command, (const char*) sid_to_string(leaving->id.sid));
|
||||
|
||||
|
||||
if (leaving->quit_reason == quit_banned || leaving->quit_reason == quit_kicked)
|
||||
{
|
||||
adc_msg_add_argument(command, ADC_QUI_FLAG_DISCONNECT);
|
||||
@@ -255,7 +261,6 @@ void uman_send_quit_message(struct hub_info* hub, struct hub_user* leaving)
|
||||
adc_msg_free(command);
|
||||
}
|
||||
|
||||
|
||||
sid_t uman_get_free_sid(struct hub_info* hub, struct hub_user* user)
|
||||
{
|
||||
sid_t sid = sid_alloc(hub->users->sids, user);
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
|
||||
#include "network/connection.h"
|
||||
|
||||
struct net_backend;
|
||||
struct net_connection;
|
||||
|
||||
struct net_cleanup_handler
|
||||
{
|
||||
size_t num;
|
||||
@@ -28,6 +31,163 @@ struct net_cleanup_handler
|
||||
struct net_connection** queue;
|
||||
};
|
||||
|
||||
struct net_backend
|
||||
{
|
||||
struct net_backend_common common;
|
||||
time_t now; /* the time now (used for timeout handling) */
|
||||
struct timeout_queue timeout_queue; /* used for timeout handling */
|
||||
struct net_cleanup_handler* cleaner; /* handler to cleanup connections at a safe point */
|
||||
struct net_backend_handler handler; /* backend event handler */
|
||||
struct net_backend* data; /* backend specific data */
|
||||
};
|
||||
|
||||
static struct net_backend* g_backend;
|
||||
|
||||
|
||||
#ifdef USE_EPOLL
|
||||
extern struct net_backend* net_backend_init_epoll(struct net_backend_handler*, struct net_backend_common*);
|
||||
#endif
|
||||
|
||||
#ifdef USE_KQUEUE
|
||||
extern struct net_backend* net_backend_init_kqueue(struct net_backend_handler*, struct net_backend_common*);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SELECT
|
||||
extern struct net_backend* net_backend_init_select(struct net_backend_handler*, struct net_backend_common*);
|
||||
#endif
|
||||
|
||||
static net_backend_init_t net_backend_init_funcs[] = {
|
||||
#ifdef USE_EPOLL
|
||||
net_backend_init_epoll,
|
||||
#endif
|
||||
#ifdef USE_KQUEUE
|
||||
net_backend_init_kqueue,
|
||||
#endif
|
||||
#ifdef USE_SELECT
|
||||
net_backend_init_select,
|
||||
#endif
|
||||
0
|
||||
};
|
||||
|
||||
int net_backend_init()
|
||||
{
|
||||
size_t n;
|
||||
g_backend = hub_malloc_zero(sizeof(struct net_backend));
|
||||
g_backend->common.num = 0;
|
||||
g_backend->common.max = net_get_max_sockets();
|
||||
g_backend->now = time(0);
|
||||
timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 120); /* FIXME: max 120 secs! */
|
||||
g_backend->cleaner = net_cleanup_initialize(g_backend->common.max);
|
||||
|
||||
for (n = 0; n < sizeof(net_backend_init_funcs); n++)
|
||||
{
|
||||
if (!net_backend_init_funcs[n])
|
||||
break;
|
||||
|
||||
g_backend->data = net_backend_init_funcs[n](&g_backend->handler, &g_backend->common);
|
||||
if (g_backend->data)
|
||||
{
|
||||
LOG_DEBUG("Initialized %s network backend.", g_backend->handler.backend_name());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
LOG_FATAL("Unable to find a suitable network backend");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void net_backend_shutdown()
|
||||
{
|
||||
g_backend->handler.backend_shutdown(g_backend->data);
|
||||
timeout_queue_shutdown(&g_backend->timeout_queue);
|
||||
net_cleanup_shutdown(g_backend->cleaner);
|
||||
hub_free(g_backend);
|
||||
g_backend = 0;
|
||||
}
|
||||
|
||||
|
||||
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
|
||||
{
|
||||
con->callback = callback;
|
||||
con->ptr = (void*) ptr;
|
||||
net_con_update(con, events);
|
||||
}
|
||||
|
||||
void net_con_update(struct net_connection* con, int events)
|
||||
{
|
||||
g_backend->handler.con_mod(g_backend->data, con, events);
|
||||
}
|
||||
|
||||
struct net_connection* net_con_create()
|
||||
{
|
||||
return g_backend->handler.con_create(g_backend->data);
|
||||
}
|
||||
|
||||
struct timeout_queue* net_backend_get_timeout_queue()
|
||||
{
|
||||
if (!g_backend)
|
||||
return 0;
|
||||
return &g_backend->timeout_queue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process the network backend.
|
||||
*/
|
||||
int net_backend_process()
|
||||
{
|
||||
int res;
|
||||
size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now);
|
||||
|
||||
res = g_backend->handler.backend_poll(g_backend->data, secs * 1000);
|
||||
|
||||
g_backend->now = time(0);
|
||||
timeout_queue_process(&g_backend->timeout_queue, g_backend->now);
|
||||
|
||||
if (res == -1)
|
||||
{
|
||||
LOG_WARN("backend error.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_backend->handler.backend_process(g_backend->data, res);
|
||||
|
||||
net_cleanup_process(g_backend->cleaner);
|
||||
return 1;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
g_backend->handler.con_init(g_backend->data, con, sd, callback, ptr);
|
||||
|
||||
net_set_nonblocking(con->sd, 1);
|
||||
net_set_nosigpipe(con->sd, 1);
|
||||
|
||||
g_backend->handler.con_add(g_backend->data, con, events);
|
||||
g_backend->common.num++;
|
||||
}
|
||||
|
||||
void net_con_close(struct net_connection* con)
|
||||
{
|
||||
if (con->flags & NET_CLEANUP)
|
||||
return;
|
||||
|
||||
g_backend->common.num--;
|
||||
net_con_clear_timeout(con);
|
||||
|
||||
g_backend->handler.con_del(g_backend->data, con);
|
||||
|
||||
net_close(con->sd);
|
||||
con->sd = -1;
|
||||
|
||||
net_cleanup_delayed_free(g_backend->cleaner, con);
|
||||
}
|
||||
|
||||
struct net_cleanup_handler* net_cleanup_initialize(size_t max)
|
||||
{
|
||||
struct net_cleanup_handler* handler = (struct net_cleanup_handler*) hub_malloc(sizeof(struct net_cleanup_handler));
|
||||
|
||||
@@ -20,14 +20,50 @@
|
||||
#ifndef HAVE_UHUB_NETWORK_BACKEND_H
|
||||
#define HAVE_UHUB_NETWORK_BACKEND_H
|
||||
|
||||
struct net_backend;
|
||||
struct net_backend_common;
|
||||
struct net_backend_handler;
|
||||
struct net_cleanup_handler;
|
||||
struct net_connection;
|
||||
typedef void (*net_connection_cb)(struct net_connection*, int event, void* ptr);
|
||||
|
||||
|
||||
typedef struct net_backend* (*net_backend_init_t)(struct net_backend_handler* handler, struct net_backend_common* common);
|
||||
typedef int (*net_backend_poll)(struct net_backend*, int ms);
|
||||
typedef void (*net_backend_proc)(struct net_backend*, int res);
|
||||
typedef void (*net_backend_destroy)(struct net_backend*);
|
||||
|
||||
typedef struct net_connection* (*net_con_backend_create)(struct net_backend*);
|
||||
typedef void (*net_con_backend_init)(struct net_backend*, struct net_connection*, int sd, net_connection_cb callback, const void* ptr);
|
||||
typedef void (*net_con_backend_add)(struct net_backend*, struct net_connection*, int mask);
|
||||
typedef void (*net_con_backend_mod)(struct net_backend*, struct net_connection*, int mask);
|
||||
typedef void (*net_con_backend_del)(struct net_backend*,struct net_connection*);
|
||||
typedef const char* (*net_con_backend_name)(void);
|
||||
|
||||
struct net_backend_handler
|
||||
{
|
||||
net_con_backend_name backend_name;
|
||||
net_backend_poll backend_poll;
|
||||
net_backend_proc backend_process;
|
||||
net_backend_destroy backend_shutdown;
|
||||
net_con_backend_create con_create;
|
||||
net_con_backend_init con_init;
|
||||
net_con_backend_add con_add;
|
||||
net_con_backend_mod con_mod;
|
||||
net_con_backend_del con_del;
|
||||
};
|
||||
|
||||
struct net_backend_common
|
||||
{
|
||||
size_t num; /* number of connections monitored by the backend */
|
||||
size_t max; /* max number of connections that can be monitored */
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the network backend.
|
||||
* Returns 1 on success, or 0 on failure.
|
||||
*/
|
||||
extern int net_backend_initialize();
|
||||
extern int net_backend_init();
|
||||
|
||||
/**
|
||||
* Shutdown the network connection backend.
|
||||
@@ -39,6 +75,11 @@ extern void net_backend_shutdown();
|
||||
*/
|
||||
extern int net_backend_process();
|
||||
|
||||
/**
|
||||
* Get the current time.
|
||||
*/
|
||||
time_t net_get_time();
|
||||
|
||||
extern struct timeout_queue* net_backend_get_timeout_queue();
|
||||
|
||||
struct net_cleanup_handler* net_cleanup_initialize(size_t max);
|
||||
|
||||
@@ -249,6 +249,11 @@ void* net_con_get_ptr(struct net_connection* con)
|
||||
return con->ptr;
|
||||
}
|
||||
|
||||
void net_con_destroy(struct net_connection* con)
|
||||
{
|
||||
hub_free(con);
|
||||
}
|
||||
|
||||
void net_con_callback(struct net_connection* con, int events)
|
||||
{
|
||||
if (con->flags & NET_CLEANUP)
|
||||
|
||||
@@ -28,10 +28,6 @@
|
||||
#define NET_EVENT_READ 0x0002
|
||||
#define NET_EVENT_WRITE 0x0004
|
||||
|
||||
struct net_connection;
|
||||
|
||||
typedef void (*net_connection_cb)(struct net_connection*, int event, void* ptr);
|
||||
|
||||
struct net_connection
|
||||
{
|
||||
NET_CON_STRUCT_COMMON
|
||||
|
||||
@@ -33,124 +33,55 @@ struct net_connection_epoll
|
||||
struct epoll_event ev;
|
||||
};
|
||||
|
||||
struct net_backend
|
||||
struct net_backend_epoll
|
||||
{
|
||||
int epfd;
|
||||
size_t num;
|
||||
size_t max;
|
||||
struct net_connection_epoll** conns;
|
||||
struct epoll_event events[EPOLL_EVBUFFER];
|
||||
time_t now;
|
||||
struct timeout_queue timeout_queue;
|
||||
struct net_cleanup_handler* cleaner;
|
||||
struct net_backend_common* common;
|
||||
};
|
||||
|
||||
static struct net_backend* g_backend = 0;
|
||||
static void net_backend_set_handlers(struct net_backend_handler* handler);
|
||||
|
||||
static void net_con_print(const char* prefix, struct net_connection_epoll* con)
|
||||
const char* net_backend_name_epoll()
|
||||
{
|
||||
char buf[512];
|
||||
int off = snprintf(buf, 512, "%s: net_connection={ sd=%d, flags=%u, callback=%p, ptr=%p, ev={ events=%s%s, data.ptr=%p }",
|
||||
prefix, con->sd, con->flags, con->callback, con->ptr, (con->ev.events & EPOLLIN ? "R" : ""),(con->ev.events & EPOLLOUT ? "W" : "") , con->ev.data.ptr);
|
||||
if (con->timeout)
|
||||
{
|
||||
sprintf(buf + off, ", timeout={ %d seconds left }", (int) (con->timeout->timestamp - g_backend->now));
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(buf + off, ", timeout=NULL");
|
||||
}
|
||||
LOG_TRACE(buf);
|
||||
return "epoll";
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the network backend.
|
||||
* Returns 1 on success, or 0 on failure.
|
||||
*/
|
||||
int net_backend_initialize()
|
||||
int net_backend_poll_epoll(struct net_backend* data, int ms)
|
||||
{
|
||||
size_t max = net_get_max_sockets();
|
||||
g_backend = hub_malloc(sizeof(struct net_backend));
|
||||
g_backend->epfd = epoll_create(max);
|
||||
if (g_backend->epfd == -1)
|
||||
{
|
||||
LOG_WARN("Unable to create epoll socket.");
|
||||
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||
int res = epoll_wait(backend->epfd, backend->events, MIN(backend->common->num, EPOLL_EVBUFFER), ms);
|
||||
if (res == -1 && errno == EINTR)
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_backend->num = 0;
|
||||
g_backend->max = max;
|
||||
g_backend->conns = hub_malloc_zero(sizeof(struct net_connection_epoll*) * max);
|
||||
memset(g_backend->events, 0, sizeof(g_backend->events));
|
||||
|
||||
g_backend->now = time(0);
|
||||
timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 600); /* look max 10 minutes into the future. */
|
||||
g_backend->cleaner = net_cleanup_initialize(max);
|
||||
return 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown the network connection backend.
|
||||
*/
|
||||
void net_backend_shutdown()
|
||||
void net_backend_process_epoll(struct net_backend* data, int res)
|
||||
{
|
||||
close(g_backend->epfd);
|
||||
timeout_queue_shutdown(&g_backend->timeout_queue);
|
||||
net_cleanup_shutdown(g_backend->cleaner);
|
||||
hub_free(g_backend->conns);
|
||||
hub_free(g_backend);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the network backend.
|
||||
*/
|
||||
int net_backend_process()
|
||||
{
|
||||
int n;
|
||||
size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now);
|
||||
LOG_TRACE("epoll_wait: fd=%d, events=%x, max=%zu, seconds=%d", g_backend->epfd, g_backend->events, MIN(g_backend->num, EPOLL_EVBUFFER), (int) secs);
|
||||
int res = epoll_wait(g_backend->epfd, g_backend->events, MIN(g_backend->num, EPOLL_EVBUFFER), secs * 1000);
|
||||
|
||||
g_backend->now = time(0);
|
||||
timeout_queue_process(&g_backend->timeout_queue, g_backend->now);
|
||||
|
||||
if (res == -1)
|
||||
{
|
||||
LOG_WARN("epoll_wait returned -1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n, ev;
|
||||
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||
for (n = 0; n < res; n++)
|
||||
{
|
||||
struct net_connection_epoll* con = (struct net_connection_epoll*) g_backend->events[n].data.ptr;
|
||||
int ev = 0;
|
||||
if (g_backend->events[n].events & EPOLLIN) ev |= NET_EVENT_READ;
|
||||
if (g_backend->events[n].events & EPOLLOUT) ev |= NET_EVENT_WRITE;
|
||||
net_con_callback((struct net_connection*) con, ev);
|
||||
struct net_connection_epoll* con = backend->conns[backend->events[n].data.fd];
|
||||
if (con)
|
||||
{
|
||||
ev = 0;
|
||||
if (backend->events[n].events & EPOLLIN) ev |= NET_EVENT_READ;
|
||||
if (backend->events[n].events & EPOLLOUT) ev |= NET_EVENT_WRITE;
|
||||
net_con_callback((struct net_connection*) con, ev);
|
||||
}
|
||||
}
|
||||
|
||||
net_cleanup_process(g_backend->cleaner);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct timeout_queue* net_backend_get_timeout_queue()
|
||||
{
|
||||
return &g_backend->timeout_queue;
|
||||
}
|
||||
|
||||
struct net_connection* net_con_create()
|
||||
struct net_connection* net_con_create_epoll(struct net_backend* data)
|
||||
{
|
||||
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_epoll));
|
||||
con->sd = -1;
|
||||
return con;
|
||||
}
|
||||
|
||||
void net_con_destroy(struct net_connection* con)
|
||||
{
|
||||
hub_free(con);
|
||||
}
|
||||
|
||||
void net_con_initialize(struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr, int events)
|
||||
void net_con_initialize_epoll(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr)
|
||||
{
|
||||
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
||||
con->sd = sd;
|
||||
@@ -158,35 +89,30 @@ void net_con_initialize(struct net_connection* con_, int sd, net_connection_cb c
|
||||
con->callback = callback;
|
||||
con->ev.events = 0;
|
||||
con->ptr = (void*) ptr;
|
||||
con->ev.data.ptr = (void*) con;
|
||||
con->ev.data.fd = sd;
|
||||
}
|
||||
|
||||
net_set_nonblocking(con->sd, 1);
|
||||
net_set_nosigpipe(con->sd, 1);
|
||||
void net_con_backend_add_epoll(struct net_backend* data, struct net_connection* con_, int events)
|
||||
{
|
||||
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
||||
|
||||
if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN;
|
||||
backend->conns[con->sd] = con;
|
||||
|
||||
if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN;
|
||||
if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT;
|
||||
|
||||
g_backend->conns[sd] = con;
|
||||
g_backend->num++;
|
||||
|
||||
if (epoll_ctl(g_backend->epfd, EPOLL_CTL_ADD, con->sd, &con->ev) == -1)
|
||||
if (epoll_ctl(backend->epfd, EPOLL_CTL_ADD, con->sd, &con->ev) == -1)
|
||||
{
|
||||
LOG_TRACE("epoll_ctl() add failed.");
|
||||
}
|
||||
|
||||
net_con_print("ADD", con);
|
||||
}
|
||||
|
||||
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
|
||||
{
|
||||
con->callback = callback;
|
||||
con->ptr = (void*) ptr;
|
||||
net_con_update(con, events);
|
||||
}
|
||||
|
||||
void net_con_update(struct net_connection* con_, int events)
|
||||
void net_con_backend_mod_epoll(struct net_backend* data, struct net_connection* con_, int events)
|
||||
{
|
||||
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
||||
|
||||
int newev = 0;
|
||||
if (events & NET_EVENT_READ) newev |= EPOLLIN;
|
||||
if (events & NET_EVENT_WRITE) newev |= EPOLLOUT;
|
||||
@@ -195,37 +121,66 @@ void net_con_update(struct net_connection* con_, int events)
|
||||
return;
|
||||
|
||||
con->ev.events = newev;
|
||||
if (epoll_ctl(g_backend->epfd, EPOLL_CTL_MOD, con->sd, &con->ev) == -1)
|
||||
if (epoll_ctl(backend->epfd, EPOLL_CTL_MOD, con->sd, &con->ev) == -1)
|
||||
{
|
||||
LOG_TRACE("epoll_ctl() modify failed.");
|
||||
}
|
||||
net_con_print("MOD", con);
|
||||
}
|
||||
|
||||
void net_con_close(struct net_connection* con_)
|
||||
void net_con_backend_del_epoll(struct net_backend* data, struct net_connection* con_)
|
||||
{
|
||||
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
||||
if (con->flags & NET_CLEANUP)
|
||||
return;
|
||||
|
||||
if (con->sd != -1)
|
||||
{
|
||||
g_backend->conns[con->sd] = 0;
|
||||
g_backend->num--;
|
||||
}
|
||||
backend->conns[con->sd] = 0;
|
||||
|
||||
net_con_clear_timeout(con_);
|
||||
|
||||
if (epoll_ctl(g_backend->epfd, EPOLL_CTL_DEL, con->sd, &con->ev) == -1)
|
||||
if (epoll_ctl(backend->epfd, EPOLL_CTL_DEL, con->sd, &con->ev) == -1)
|
||||
{
|
||||
LOG_WARN("epoll_ctl() delete failed.");
|
||||
}
|
||||
}
|
||||
|
||||
net_close(con->sd);
|
||||
con->sd = -1;
|
||||
void net_backend_shutdown_epoll(struct net_backend* data)
|
||||
{
|
||||
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||
close(backend->epfd);
|
||||
hub_free(backend->conns);
|
||||
hub_free(backend);
|
||||
}
|
||||
|
||||
net_con_print("DEL", con);
|
||||
net_cleanup_delayed_free(g_backend->cleaner, con_);
|
||||
struct net_backend* net_backend_init_epoll(struct net_backend_handler* handler, struct net_backend_common* common)
|
||||
{
|
||||
struct net_backend_epoll* backend;
|
||||
|
||||
if (getenv("EVENT_NOEPOLL"))
|
||||
return 0;
|
||||
|
||||
backend = hub_malloc_zero(sizeof(struct net_backend_epoll));
|
||||
backend->epfd = epoll_create(common->max);
|
||||
if (backend->epfd == -1)
|
||||
{
|
||||
LOG_WARN("Unable to create epoll socket.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
backend->conns = hub_malloc_zero(sizeof(struct net_connection_epoll*) * common->max);
|
||||
backend->common = common;
|
||||
|
||||
net_backend_set_handlers(handler);
|
||||
return (struct net_backend*) backend;
|
||||
}
|
||||
|
||||
static void net_backend_set_handlers(struct net_backend_handler* handler)
|
||||
{
|
||||
handler->backend_name = net_backend_name_epoll;
|
||||
handler->backend_poll = net_backend_poll_epoll;
|
||||
handler->backend_process = net_backend_process_epoll;
|
||||
handler->backend_shutdown = net_backend_shutdown_epoll;
|
||||
handler->con_create = net_con_create_epoll;
|
||||
handler->con_init = net_con_initialize_epoll;
|
||||
handler->con_add = net_con_backend_add_epoll;
|
||||
handler->con_mod = net_con_backend_mod_epoll;
|
||||
handler->con_del = net_con_backend_del_epoll;
|
||||
}
|
||||
|
||||
#endif /* USE_EPOLL */
|
||||
|
||||
186
src/network/kqueue.c
Normal file
186
src/network/kqueue.c
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "uhub.h"
|
||||
|
||||
#ifdef USE_KQUEUE
|
||||
|
||||
#include "network/connection.h"
|
||||
#include "network/common.h"
|
||||
#include "network/backend.h"
|
||||
|
||||
#define KQUEUE_EVBUFFER 512
|
||||
|
||||
struct net_connection_kqueue
|
||||
{
|
||||
NET_CON_STRUCT_COMMON
|
||||
struct kevent ev;
|
||||
};
|
||||
|
||||
struct net_backend_kqueue
|
||||
{
|
||||
int kqfd;
|
||||
struct net_connection_kqueue** conns;
|
||||
struct kevent** changes;
|
||||
size_t nchanges;
|
||||
struct kevent events[KQUEUE_EVBUFFER];
|
||||
struct net_backend_common* common;
|
||||
};
|
||||
|
||||
static void net_backend_set_handlers(struct net_backend_handler* handler);
|
||||
|
||||
const char* net_backend_name_kqueue()
|
||||
{
|
||||
return "kqueue";
|
||||
}
|
||||
|
||||
int net_backend_poll_kqueue(struct net_backend* data, int ms)
|
||||
{
|
||||
int res;
|
||||
struct timespec tspec = { 0, };
|
||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||
|
||||
tspec.tv_sec = (ms / 1000);
|
||||
tspec.tv_nsec = ((ms % 1000) * 1000000); /* FIXME: correct? */
|
||||
|
||||
res = kevent(backend->kqfd, *backend->changes, backend->nchanges, backend->events, KQUEUE_EVBUFFER, &tspec);
|
||||
backend->nchanges = 0;
|
||||
|
||||
if (res == -1 && errno == EINTR)
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
void net_backend_process_kqueue(struct net_backend* data, int res)
|
||||
{
|
||||
int n;
|
||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||
|
||||
for (n = 0; n < res; n++)
|
||||
{
|
||||
struct net_connection_kqueue* con = (struct net_connection_kqueue*) backend->events[n].udata;
|
||||
int ev = 0;
|
||||
if (backend->events[n].filter & EVFILT_READ) ev |= NET_EVENT_READ;
|
||||
if (backend->events[n].filter & EVFILT_WRITE) ev |= NET_EVENT_WRITE;
|
||||
net_con_callback((struct net_connection*) con, ev);
|
||||
}
|
||||
}
|
||||
|
||||
struct net_connection* net_con_create_kqueue(struct net_backend* data)
|
||||
{
|
||||
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_kqueue));
|
||||
con->sd = -1;
|
||||
return con;
|
||||
}
|
||||
|
||||
void net_con_initialize_kqueue(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr)
|
||||
{
|
||||
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||
con->sd = sd;
|
||||
con->flags = 0;
|
||||
con->callback = callback;
|
||||
con->ptr = (void*) ptr;
|
||||
}
|
||||
|
||||
void net_con_backend_add_kqueue(struct net_backend* data, struct net_connection* con_, int events)
|
||||
{
|
||||
short filter = 0;
|
||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||
if (events & NET_EVENT_READ) filter |= EVFILT_READ;
|
||||
if (events & NET_EVENT_WRITE) filter |= EVFILT_READ;
|
||||
EV_SET(&con->ev, con->sd, filter, EV_ADD, 0, 0, con);
|
||||
backend->changes[backend->nchanges++] = &con->ev;
|
||||
backend->conns[con->sd] = con;
|
||||
}
|
||||
|
||||
void net_con_backend_mod_kqueue(struct net_backend* data, struct net_connection* con_, int events)
|
||||
{
|
||||
short filter = 0;
|
||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||
|
||||
if (events & NET_EVENT_READ) filter |= EVFILT_READ;
|
||||
if (events & NET_EVENT_WRITE) filter |= EVFILT_READ;
|
||||
|
||||
if (filter == con->ev.filter)
|
||||
return;
|
||||
|
||||
EV_SET(&con->ev, con->sd, filter, EV_ADD, 0, 0, con);
|
||||
backend->changes[backend->nchanges++] = &con->ev;
|
||||
}
|
||||
|
||||
void net_con_backend_del_kqueue(struct net_backend* data, struct net_connection* con_)
|
||||
{
|
||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||
|
||||
backend->conns[con->sd] = 0;
|
||||
|
||||
/* No need to remove it from the kqueue filter, the kqueue man page says
|
||||
it is automatically removed when the descriptor is closed. */
|
||||
}
|
||||
|
||||
void net_backend_shutdown_kqueue(struct net_backend* data)
|
||||
{
|
||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||
close(backend->kqfd);
|
||||
hub_free(backend->conns);
|
||||
hub_free(backend->changes);
|
||||
hub_free(backend);
|
||||
}
|
||||
|
||||
struct net_backend* net_backend_init_kqueue(struct net_backend_handler* handler, struct net_backend_common* common)
|
||||
{
|
||||
struct net_backend_kqueue* backend;
|
||||
|
||||
if (getenv("EVENT_NOKQUEUE"))
|
||||
return 0;
|
||||
|
||||
backend = hub_malloc_zero(sizeof(struct net_backend_kqueue));
|
||||
backend->kqfd = kqueue();
|
||||
if (backend->kqfd == -1)
|
||||
{
|
||||
LOG_WARN("Unable to create kqueue socket.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
backend->conns = hub_malloc_zero(sizeof(struct net_connection_kqueue*) * common->max);
|
||||
backend->conns = hub_malloc_zero(sizeof(struct net_connection_kqueue*) * common->max);
|
||||
backend->changes = hub_malloc_zero(sizeof(struct kevent*) * common->max);
|
||||
backend->common = common;
|
||||
|
||||
net_backend_set_handlers(handler);
|
||||
return (struct net_backend*) backend;
|
||||
}
|
||||
|
||||
static void net_backend_set_handlers(struct net_backend_handler* handler)
|
||||
{
|
||||
handler->backend_name = net_backend_name_kqueue;
|
||||
handler->backend_poll = net_backend_poll_kqueue;
|
||||
handler->backend_process = net_backend_process_kqueue;
|
||||
handler->backend_shutdown = net_backend_shutdown_kqueue;
|
||||
handler->con_create = net_con_create_kqueue;
|
||||
handler->con_init = net_con_initialize_kqueue;
|
||||
handler->con_add = net_con_backend_add_kqueue;
|
||||
handler->con_mod = net_con_backend_mod_kqueue;
|
||||
handler->con_del = net_con_backend_del_kqueue;
|
||||
}
|
||||
|
||||
#endif /* USE_KQUEUE */
|
||||
@@ -47,7 +47,13 @@ int net_initialize()
|
||||
}
|
||||
#endif /* WINSOCK */
|
||||
|
||||
net_backend_initialize();
|
||||
if (!net_backend_init())
|
||||
{
|
||||
#ifdef WINSOCK
|
||||
WSACleanup();
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
net_stats_initialize();
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
@@ -69,7 +75,7 @@ size_t net_get_max_sockets()
|
||||
struct rlimit limits;
|
||||
if (getrlimit(RLIMIT_NOFILE, &limits) == 0)
|
||||
{
|
||||
return limits.rlim_max;
|
||||
return MIN(limits.rlim_max, 65536);
|
||||
}
|
||||
LOG_ERROR("getrlimit() failed");
|
||||
return 1024;
|
||||
@@ -351,6 +357,9 @@ int net_accept(int fd, struct ip_addr_encap* ipaddr)
|
||||
{
|
||||
switch (net_error())
|
||||
{
|
||||
#if defined(__HAIKU__)
|
||||
case ETIMEDOUT:
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
case ENETDOWN:
|
||||
case EPROTO:
|
||||
@@ -588,9 +597,10 @@ const char* net_get_peer_address(int fd)
|
||||
struct sockaddr_in6* name6;
|
||||
struct sockaddr_in* name4;
|
||||
struct sockaddr* name;
|
||||
socklen_t namelen;
|
||||
|
||||
memset(address, 0, INET6_ADDRSTRLEN);
|
||||
socklen_t namelen = sizeof(struct sockaddr_storage);
|
||||
namelen = sizeof(struct sockaddr_storage);
|
||||
memset(&storage, 0, namelen);
|
||||
|
||||
name6 = (struct sockaddr_in6*) &storage;
|
||||
@@ -626,9 +636,10 @@ const char* net_get_local_address(int fd)
|
||||
struct sockaddr_in6* name6;
|
||||
struct sockaddr_in* name4;
|
||||
struct sockaddr* name;
|
||||
socklen_t namelen;
|
||||
|
||||
memset(address, 0, INET6_ADDRSTRLEN);
|
||||
socklen_t namelen = sizeof(struct sockaddr_storage);
|
||||
namelen = sizeof(struct sockaddr_storage);
|
||||
memset(&storage, 0, namelen);
|
||||
|
||||
name6 = (struct sockaddr_in6*) &storage;
|
||||
|
||||
@@ -30,110 +30,67 @@ struct net_connection_select
|
||||
NET_CON_STRUCT_COMMON
|
||||
};
|
||||
|
||||
struct net_backend
|
||||
struct net_backend_select
|
||||
{
|
||||
size_t num;
|
||||
size_t max;
|
||||
struct net_connection_select** conns;
|
||||
fd_set rfds;
|
||||
fd_set wfds;
|
||||
time_t now;
|
||||
struct timeout_queue timeout_queue;
|
||||
struct net_cleanup_handler* cleaner;
|
||||
int maxfd;
|
||||
struct net_backend_common* common;
|
||||
};
|
||||
|
||||
static struct net_backend* g_backend = 0;
|
||||
static void net_backend_set_handlers(struct net_backend_handler* handler);
|
||||
|
||||
static void net_con_print(const char* prefix, struct net_connection_select* con)
|
||||
const char* net_backend_name_select()
|
||||
{
|
||||
char buf[512];
|
||||
int off = snprintf(buf, 512, "%s: net_connection={ sd=%d, flags=%u, callback=%p, ptr=%p, events=%s%s",
|
||||
prefix, con->sd, con->flags, con->callback, con->ptr, (con->flags & NET_EVENT_READ ? "R" : ""),(con->flags & NET_EVENT_WRITE ? "W" : ""));
|
||||
if (con->timeout)
|
||||
{
|
||||
sprintf(buf + off, ", timeout={ %d seconds left }", (int) (con->timeout->timestamp - g_backend->now));
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(buf + off, ", timeout=NULL");
|
||||
}
|
||||
LOG_TRACE(buf);
|
||||
return "select";
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the network backend.
|
||||
* Returns 1 on success, or 0 on failure.
|
||||
*/
|
||||
int net_backend_initialize()
|
||||
int net_backend_poll_select(struct net_backend* data, int ms)
|
||||
{
|
||||
size_t max = net_get_max_sockets();
|
||||
g_backend = hub_malloc(sizeof(struct net_backend));
|
||||
g_backend->num = 0;
|
||||
g_backend->max = max;
|
||||
g_backend->conns = hub_malloc_zero(sizeof(struct net_connection_select*) * max);
|
||||
FD_ZERO(&g_backend->rfds);
|
||||
FD_ZERO(&g_backend->wfds);
|
||||
g_backend->now = time(0);
|
||||
timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 600); /* look max 10 minutes into the future. */
|
||||
g_backend->cleaner = net_cleanup_initialize(max);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown the network connection backend.
|
||||
*/
|
||||
void net_backend_shutdown()
|
||||
{
|
||||
timeout_queue_shutdown(&g_backend->timeout_queue);
|
||||
net_cleanup_shutdown(g_backend->cleaner);
|
||||
hub_free(g_backend->conns);
|
||||
hub_free(g_backend);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the network backend.
|
||||
*/
|
||||
int net_backend_process()
|
||||
{
|
||||
int n, found, maxfd;
|
||||
int found, res, n;
|
||||
struct timeval tval;
|
||||
FD_ZERO(&g_backend->rfds);
|
||||
FD_ZERO(&g_backend->wfds);
|
||||
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||
|
||||
size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now);
|
||||
tval.tv_secs = secs;
|
||||
tval.tv_usecs = 0;
|
||||
tval.tv_sec = ms / 1000;
|
||||
tval.tv_usec = ((ms % 1000) * 1000); // FIXME: correct?
|
||||
|
||||
for (n = 0, found = 0; found < g_backend->num && n < g_backend->max; n++)
|
||||
FD_ZERO(&backend->rfds);
|
||||
FD_ZERO(&backend->wfds);
|
||||
|
||||
backend->maxfd = -1;
|
||||
for (n = 0, found = 0; found < backend->common->num && n < backend->common->max; n++)
|
||||
{
|
||||
struct net_connection_select* con = g_backend->conns[n];
|
||||
struct net_connection_select* con = backend->conns[n];
|
||||
if (con)
|
||||
{
|
||||
if (con->flags & NET_EVENT_READ) FD_SET(con->sd, &g_backend->rfds);
|
||||
if (con->flags & NET_EVENT_WRITE) FD_SET(con->sd, &g_backend->wfds);
|
||||
if (con->flags & NET_EVENT_READ) FD_SET(con->sd, &backend->rfds);
|
||||
if (con->flags & NET_EVENT_WRITE) FD_SET(con->sd, &backend->wfds);
|
||||
found++;
|
||||
maxfd = con->sd;
|
||||
backend->maxfd = con->sd;
|
||||
}
|
||||
}
|
||||
backend->maxfd++;
|
||||
|
||||
int res = select(maxfd+1, &g_backend->rfds, &g_backend->wfds, 0, &tval);
|
||||
g_backend->now = time(0);
|
||||
timeout_queue_process(&g_backend->timeout_queue, g_backend->now);
|
||||
res = select(backend->maxfd, &backend->rfds, &backend->wfds, 0, &tval);
|
||||
|
||||
if (res == -1)
|
||||
{
|
||||
LOG_WARN("select returned -1");
|
||||
if (res == -1 && errno == EINTR)
|
||||
return 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
for (n = 0, found = 0; found < res && n < (maxfd+1); n++)
|
||||
void net_backend_process_select(struct net_backend* data, int res)
|
||||
{
|
||||
int n, found;
|
||||
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||
for (n = 0, found = 0; found < res && n < backend->maxfd; n++)
|
||||
{
|
||||
struct net_connection_select* con = g_backend->conns[n];
|
||||
struct net_connection_select* con = backend->conns[n];
|
||||
if (con)
|
||||
{
|
||||
int ev = 0;
|
||||
if (FD_ISSET(con->sd, &g_backend->rfds)) ev |= NET_EVENT_READ;
|
||||
if (FD_ISSET(con->sd, &g_backend->wfds)) ev |= NET_EVENT_WRITE;
|
||||
if (FD_ISSET(con->sd, &backend->rfds)) ev |= NET_EVENT_READ;
|
||||
if (FD_ISSET(con->sd, &backend->wfds)) ev |= NET_EVENT_WRITE;
|
||||
|
||||
if (ev)
|
||||
{
|
||||
@@ -142,75 +99,75 @@ int net_backend_process()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
net_cleanup_process(g_backend->cleaner);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct timeout_queue* net_backend_get_timeout_queue()
|
||||
{
|
||||
return &g_backend->timeout_queue;
|
||||
}
|
||||
|
||||
struct net_connection* net_con_create()
|
||||
struct net_connection* net_con_create_select(struct net_backend* data)
|
||||
{
|
||||
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_select));
|
||||
con->sd = -1;
|
||||
return con;
|
||||
}
|
||||
|
||||
void net_con_destroy(struct net_connection* con)
|
||||
{
|
||||
hub_free(con);
|
||||
}
|
||||
|
||||
void net_con_initialize(struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr, int events)
|
||||
void net_con_initialize_select(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr)
|
||||
{
|
||||
struct net_connection_select* con = (struct net_connection_select*) con_;
|
||||
con->sd = sd;
|
||||
con->flags = events;
|
||||
con->flags = 0;
|
||||
con->callback = callback;
|
||||
con->ptr = (void*) ptr;
|
||||
|
||||
net_set_nonblocking(con->sd, 1);
|
||||
net_set_nosigpipe(con->sd, 1);
|
||||
|
||||
g_backend->conns[sd] = con;
|
||||
g_backend->num++;
|
||||
net_con_print("ADD", con);
|
||||
}
|
||||
|
||||
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
|
||||
void net_con_backend_add_select(struct net_backend* data, struct net_connection* con, int events)
|
||||
{
|
||||
con->callback = callback;
|
||||
con->ptr = (void*) ptr;
|
||||
net_con_update(con, events);
|
||||
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||
backend->conns[con->sd] = (struct net_connection_select*) con;
|
||||
}
|
||||
|
||||
void net_con_update(struct net_connection* con, int events)
|
||||
void net_con_backend_mod_select(struct net_backend* data, struct net_connection* con, int events)
|
||||
{
|
||||
con->flags = events;
|
||||
net_con_print("MOD", (struct net_connection_select*) con);
|
||||
con->flags |= (events & (NET_EVENT_READ | NET_EVENT_WRITE));;
|
||||
}
|
||||
|
||||
void net_con_close(struct net_connection* con)
|
||||
void net_con_backend_del_select(struct net_backend* data, struct net_connection* con)
|
||||
{
|
||||
if (con->flags & NET_CLEANUP)
|
||||
return;
|
||||
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||
backend->conns[con->sd] = 0;
|
||||
}
|
||||
|
||||
if (con->sd != -1)
|
||||
{
|
||||
g_backend->conns[con->sd] = 0;
|
||||
g_backend->num--;
|
||||
}
|
||||
void net_backend_shutdown_select(struct net_backend* data)
|
||||
{
|
||||
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||
hub_free(backend->conns);
|
||||
hub_free(backend);
|
||||
}
|
||||
|
||||
net_con_clear_timeout(con);
|
||||
struct net_backend* net_backend_init_select(struct net_backend_handler* handler, struct net_backend_common* common)
|
||||
{
|
||||
struct net_backend_select* backend;
|
||||
|
||||
net_close(con->sd);
|
||||
con->sd = -1;
|
||||
if (getenv("EVENT_NOSELECT"))
|
||||
return 0;
|
||||
|
||||
net_con_print("DEL", (struct net_connection_select*) con);
|
||||
net_cleanup_delayed_free(g_backend->cleaner, con);
|
||||
backend = hub_malloc_zero(sizeof(struct net_backend_select));
|
||||
FD_ZERO(&backend->rfds);
|
||||
FD_ZERO(&backend->wfds);
|
||||
backend->conns = hub_malloc_zero(sizeof(struct net_connection_select*) * common->max);
|
||||
backend->common = common;
|
||||
net_backend_set_handlers(handler);
|
||||
return (struct net_backend*) backend;
|
||||
}
|
||||
|
||||
static void net_backend_set_handlers(struct net_backend_handler* handler)
|
||||
{
|
||||
handler->backend_name = net_backend_name_select;
|
||||
handler->backend_poll = net_backend_poll_select;
|
||||
handler->backend_process = net_backend_process_select;
|
||||
handler->backend_shutdown = net_backend_shutdown_select;
|
||||
handler->con_create = net_con_create_select;
|
||||
handler->con_init = net_con_initialize_select;
|
||||
handler->con_add = net_con_backend_add_select;
|
||||
handler->con_mod = net_con_backend_mod_select;
|
||||
handler->con_del = net_con_backend_del_select;
|
||||
}
|
||||
|
||||
#endif /* USE_SELECT */
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
*/
|
||||
|
||||
#include "uhub.h"
|
||||
#include "util/timeout.h"
|
||||
|
||||
void timeout_evt_initialize(struct timeout_evt* t, timeout_evt_cb cb, void* ptr)
|
||||
{
|
||||
@@ -36,7 +35,7 @@ void timeout_evt_reset(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)
|
||||
@@ -55,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 pos;
|
||||
size_t pos = t->last;
|
||||
size_t events = 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]))
|
||||
{
|
||||
@@ -67,7 +67,6 @@ size_t timeout_queue_process(struct timeout_queue* t, time_t now)
|
||||
events++;
|
||||
}
|
||||
}
|
||||
t->last = now;
|
||||
return events;
|
||||
}
|
||||
|
||||
@@ -95,6 +94,7 @@ void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size
|
||||
|
||||
if (first)
|
||||
{
|
||||
uhub_assert(first->timestamp == evt->timestamp);
|
||||
first->prev->next = evt;
|
||||
evt->prev = first->prev;
|
||||
first->prev = evt;
|
||||
116
src/system.h
116
src/system.h
@@ -44,6 +44,10 @@
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || (defined(__APPLE__) && defined(__MACH__))
|
||||
#define BSD_LIKE
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__) || defined(__MINGW32__)
|
||||
#ifndef WINSOCK
|
||||
#define WINSOCK
|
||||
@@ -66,11 +70,15 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef __sun__
|
||||
#include <getopt.h>
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
@@ -81,7 +89,9 @@
|
||||
#include <pwd.h>
|
||||
#include <sys/resource.h>
|
||||
#define HAVE_STRNDUP
|
||||
#ifndef __HAIKU__
|
||||
#define HAVE_MEMMEM
|
||||
#endif
|
||||
#define HAVE_GETRLIMIT
|
||||
#endif
|
||||
|
||||
@@ -105,16 +115,110 @@
|
||||
#ifdef __linux__
|
||||
#define USE_EPOLL
|
||||
#include <sys/epoll.h>
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef BSD_LIKE
|
||||
#define USE_KQUEUE
|
||||
#include <sys/event.h>
|
||||
#endif
|
||||
|
||||
#define USE_SELECT
|
||||
#ifndef WINSOCK
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun__)
|
||||
#if defined(BSD_LIKE) || defined(__sun__)
|
||||
#undef HAVE_STRNDUP
|
||||
#undef HAVE_MEMMEM
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Detect operating system info.
|
||||
* See: http://predef.sourceforge.net/
|
||||
*/
|
||||
#if defined(__linux__)
|
||||
#define OPSYS "Linux"
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(__MINGW32__) || defined(_WIN64) || defined(__WIN32__) || defined(__WINDOWS__)
|
||||
#define OPSYS "Windows"
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
#define OPSYS "MacOSX"
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#define OPSYS "FreeBSD"
|
||||
#endif
|
||||
|
||||
#if defined(__OpenBSD__)
|
||||
#define OPSYS "OpenBSD"
|
||||
#endif
|
||||
|
||||
#if defined(__NetBSD__)
|
||||
#define OPSYS "NetBSD"
|
||||
#endif
|
||||
|
||||
#if defined(__sun__)
|
||||
#if defined(__SVR4) || defined(__svr4__)
|
||||
#define OPSYS "Solaris"
|
||||
#else
|
||||
#define OPSYS "SunOS"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__HAIKU__)
|
||||
#define OPSYS "Haiku"
|
||||
#endif
|
||||
|
||||
/* Detect CPUs */
|
||||
#if defined(__alpha__) || defined(__alpha)
|
||||
#define CPUINFO "Alpha"
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) || defined(_M_X64)
|
||||
#define CPUINFO "AMD64"
|
||||
#endif
|
||||
|
||||
#if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(__TARGET_ARCH_ARM)
|
||||
#define CPUINFO "ARM"
|
||||
#endif
|
||||
|
||||
#if defined(__i386__) || defined(__i386) || defined(i386) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) || defined(__I86__) || defined(__INTEL__) || defined(__THW_INTEL__)
|
||||
#define CPUINFO "i386"
|
||||
#endif
|
||||
|
||||
#if defined(__ia64__) || defined(_IA64) || defined(__IA64__) || defined(__ia64) || defined(_M_IA64)
|
||||
#define CPUINFO "IA64"
|
||||
#endif
|
||||
|
||||
#if defined(__hppa__) || defined(__hppa)
|
||||
#define CPUINFO "PARISC"
|
||||
#endif
|
||||
|
||||
#if defined(__m68k__) || defined(M68000)
|
||||
#define CPUINFO "M68K"
|
||||
#endif
|
||||
|
||||
#if defined(__mips__) || defined(mips) || defined(__mips) || defined(__MIPS__)
|
||||
#define CPUINFO "MIPS"
|
||||
#endif
|
||||
|
||||
#if defined(__POWERPC__) || defined(__ppc__) || defined(_ARCH_PPC) || defined(__powerpc) || defined(__powerpc__)
|
||||
#define CPUINFO "PowerPC"
|
||||
#endif
|
||||
|
||||
#if defined(__sparc__) || defined(__sparc)
|
||||
#define CPUINFO "SPARC"
|
||||
#endif
|
||||
|
||||
#if defined(__sh__)
|
||||
#define CPUINFO "SuperH"
|
||||
#endif
|
||||
|
||||
/* Misc */
|
||||
#ifdef MSG_NOSIGNAL
|
||||
#define UHUB_SEND_SIGNAL MSG_NOSIGNAL
|
||||
#else
|
||||
@@ -129,8 +233,12 @@
|
||||
#define INET6_ADDRSTRLEN 46
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_UHUB_SYSTEM_H */
|
||||
|
||||
@@ -62,16 +62,17 @@ extern "C" {
|
||||
#include "util/log.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/misc.h"
|
||||
#include "util/timeout.h"
|
||||
#include "util/tiger.h"
|
||||
|
||||
#include "adc/sid.h"
|
||||
#include "adc/message.h"
|
||||
#include "network/network.h"
|
||||
#include "network/connection.h"
|
||||
#include "network/timeout.h"
|
||||
|
||||
#include "core/auth.h"
|
||||
#include "core/config.h"
|
||||
#include "core/floodctl.h"
|
||||
#include "core/eventid.h"
|
||||
#include "core/eventqueue.h"
|
||||
#include "core/netevent.h"
|
||||
|
||||
@@ -451,11 +451,12 @@ int ip_convert_address_to_range(const char* address, struct ip_range* range)
|
||||
{
|
||||
int ret = 0;
|
||||
char* addr = 0;
|
||||
const char* split;
|
||||
|
||||
if (!address || !range)
|
||||
return 0;
|
||||
|
||||
const char* split = strrchr(address, '/');
|
||||
split = strrchr(address, '/');
|
||||
if (split)
|
||||
{
|
||||
int mask = uhub_atoi(split+1);
|
||||
|
||||
@@ -171,14 +171,65 @@ void base32_decode(const char* src, unsigned char* dst, size_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
int string_split(const char* string, const char* split, void* data, string_split_handler_t handler)
|
||||
{
|
||||
char* buf = strdup(string);
|
||||
char* start;
|
||||
char* pos;
|
||||
int count = 0;
|
||||
|
||||
start = buf;
|
||||
while ((pos = strstr(start, split)))
|
||||
{
|
||||
pos[0] = '\0';
|
||||
start = strip_white_space(start);
|
||||
if (*start)
|
||||
{
|
||||
if (handler(start, count, data) < 0)
|
||||
{
|
||||
hub_free(buf);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
start = &pos[1];
|
||||
count++;
|
||||
}
|
||||
|
||||
start = strip_white_space(start);
|
||||
if (*start)
|
||||
{
|
||||
if (handler(start, count, data) < 0)
|
||||
{
|
||||
hub_free(buf);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
hub_free(buf);
|
||||
return count+1;
|
||||
}
|
||||
|
||||
struct file_read_line_data
|
||||
{
|
||||
file_line_handler_t handler;
|
||||
void* data;
|
||||
};
|
||||
|
||||
static int file_read_line_handler(char* line, int count, void* ptr)
|
||||
{
|
||||
struct file_read_line_data* data = (struct file_read_line_data*) ptr;
|
||||
|
||||
LOG_DUMP("Line: %s", line);
|
||||
if (data->handler(line, count+1, data->data) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int file_read_lines(const char* file, void* data, file_line_handler_t handler)
|
||||
{
|
||||
int fd;
|
||||
ssize_t ret;
|
||||
char buf[MAX_RECV_BUF];
|
||||
char *pos, *start;
|
||||
size_t line_count = 0;
|
||||
struct file_read_line_data split_data;
|
||||
|
||||
memset(buf, 0, MAX_RECV_BUF);
|
||||
|
||||
@@ -192,46 +243,24 @@ int file_read_lines(const char* file, void* data, file_line_handler_t handler)
|
||||
}
|
||||
|
||||
ret = read(fd, buf, MAX_RECV_BUF);
|
||||
close(fd);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERROR("Unable to read from file %s: %s", file, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
close(fd);
|
||||
LOG_WARN("File is empty.");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
close(fd);
|
||||
|
||||
/* Parse configuaration */
|
||||
start = buf;
|
||||
while ((pos = strchr(start, '\n')))
|
||||
{
|
||||
pos[0] = '\0';
|
||||
if (*start)
|
||||
{
|
||||
LOG_DUMP("Line: %s", start);
|
||||
if (handler(start, line_count+1, data) < 0)
|
||||
return -1;
|
||||
}
|
||||
start = &pos[1];
|
||||
line_count++;
|
||||
}
|
||||
|
||||
if (*start)
|
||||
{
|
||||
buf[strlen(start)] = 0;
|
||||
LOG_DUMP("Line: %s", start);
|
||||
if (handler(start, line_count+1, data) < 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return line_count+1;
|
||||
|
||||
/* Parse configuaration */
|
||||
split_data.handler = handler;
|
||||
split_data.data = data;
|
||||
|
||||
return string_split(buf, "\n", &split_data, file_read_line_handler);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ extern char* strip_white_space(char* string);
|
||||
|
||||
extern int file_read_lines(const char* file, void* data, file_line_handler_t handler);
|
||||
|
||||
|
||||
extern const char* uhub_itoa(int val);
|
||||
extern const char* uhub_ulltoa(uint64_t val);
|
||||
|
||||
@@ -61,6 +62,8 @@ void* memmem(const void *haystack, size_t haystacklen, const void *needle, size_
|
||||
struct linked_list;
|
||||
extern int split_string(const char* string, const char* split, struct linked_list* list, int allow_empty);
|
||||
|
||||
typedef int (*string_split_handler_t)(char* string, int count, void* data);
|
||||
extern int string_split(const char* string, const char* split, void* data, string_split_handler_t handler);
|
||||
|
||||
#endif /* HAVE_UHUB_MISC_H */
|
||||
|
||||
|
||||
20
tools/nmdc-redirector
Executable file
20
tools/nmdc-redirector
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
# Setup using inetd/xinetd or similar.
|
||||
# In /etc/inetd.conf add:
|
||||
# 1511 stream tcp nowait nobody /usr/bin/nmdc-redirector adc://target:port
|
||||
#
|
||||
# Change port to whatever you want.
|
||||
# Make sure the path and the target:port is correct, then you should be good
|
||||
# to go!
|
||||
|
||||
use strict;
|
||||
use IO::Handle;
|
||||
autoflush STDIN;
|
||||
autoflush STDOUT;
|
||||
|
||||
my $target = $ARGV[0];
|
||||
|
||||
print "<Redirector> You are being redirected to " . $target . "|";
|
||||
print "\$ForceMove " . $target . "|";
|
||||
|
||||
20
version.h
20
version.h
@@ -1,17 +1,25 @@
|
||||
#include "revision.h"
|
||||
|
||||
#ifndef PRODUCT
|
||||
#define PRODUCT "uHub"
|
||||
#define PRODUCT "uhub"
|
||||
#endif
|
||||
|
||||
#ifndef VERSION
|
||||
#define VERSION "0.3.1"
|
||||
#endif
|
||||
|
||||
#ifndef GIT_REVISION
|
||||
#define REVISION ""
|
||||
#define PRODUCT_STRING PRODUCT "/" VERSION
|
||||
#else
|
||||
#define REVISION " (git: " GIT_REVISION ")"
|
||||
#define REVISION "(git: " GIT_REVISION ")"
|
||||
#ifdef GIT_VERSION
|
||||
#define PRODUCT_STRING PRODUCT "/" GIT_VERSION
|
||||
#else
|
||||
#define PRODUCT_STRING PRODUCT "/" VERSION " " REVISION
|
||||
#endif
|
||||
|
||||
#ifndef VERSION
|
||||
#define VERSION "0.3.0" REVISION
|
||||
#endif
|
||||
|
||||
#ifndef COPYRIGHT
|
||||
#define COPYRIGHT "Copyright (c) 2007-2009, Jan Vidar Krey <janvidar@extatic.org>"
|
||||
#define COPYRIGHT "Copyright (c) 2007-2010, Jan Vidar Krey <janvidar@extatic.org>"
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user