Compare commits
1 Commits
0.3.1-rc2
...
0.2.x-stab
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1cd5bb535 |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,8 +0,0 @@
|
|||||||
*~
|
|
||||||
*.[oa]
|
|
||||||
*.exe
|
|
||||||
*.gch
|
|
||||||
uhub-admin
|
|
||||||
adcrush
|
|
||||||
uhub
|
|
||||||
|
|
||||||
2
AUTHORS
2
AUTHORS
@@ -2,5 +2,5 @@ Authors of uHub
|
|||||||
===============
|
===============
|
||||||
|
|
||||||
Jan Vidar Krey, Design and implementation
|
Jan Vidar Krey, Design and implementation
|
||||||
E_zombie, Centos/RedHat customization scripts and heavy load testing
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
|
|
||||||
GMAKE=gmake
|
|
||||||
|
|
||||||
all:
|
|
||||||
@${GMAKE} ${.TARGETS}
|
|
||||||
|
|
||||||
${.TARGETS}: all
|
|
||||||
|
|
||||||
12
ChangeLog
12
ChangeLog
@@ -1,15 +1,3 @@
|
|||||||
0.3.0:
|
|
||||||
- More user commands: ban, broadcast, mute, rules, history, myip, whoip, log
|
|
||||||
- Experimental SSL support
|
|
||||||
- Large rewrite of the network stack in order to support SSL.
|
|
||||||
- Added rule file for defining hub rules.
|
|
||||||
- Many crash fixes and other important bug fixes.
|
|
||||||
- Optimizations: O(1) timeout scheduler
|
|
||||||
- New sid allocation code.
|
|
||||||
- Added configurable server_listen_backlog (default 50).
|
|
||||||
- Added init.d scripts for RedHat/CentOS
|
|
||||||
|
|
||||||
|
|
||||||
0.2.8:
|
0.2.8:
|
||||||
- Fix bug #13: getsockname() failure, use sockaddr from accept() instead.
|
- Fix bug #13: getsockname() failure, use sockaddr from accept() instead.
|
||||||
- Fix bug #10: Improve logging, ensure logs are machine readable.
|
- Fix bug #10: Improve logging, ensure logs are machine readable.
|
||||||
|
|||||||
212
GNUmakefile
212
GNUmakefile
@@ -1,40 +1,27 @@
|
|||||||
##
|
##
|
||||||
## Makefile for uhub (Use GNU make)
|
## Makefile for uhub (Use GNU make)
|
||||||
## Copyright (C) 2007-2010, Jan Vidar Krey <janvidar@extatic.org>
|
## Copyright (C) 2007-2008, Jan Vidar Krey <janvidar@extatic.org>
|
||||||
#
|
#
|
||||||
|
|
||||||
-include Makefile.private
|
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
LD := $(CC)
|
LD := $(CC)
|
||||||
MV := mv
|
MV := mv
|
||||||
RANLIB := ranlib
|
RANLIB := ranlib
|
||||||
CFLAGS += -pipe -Wall
|
CFLAGS += -pipe -Wall
|
||||||
|
USE_PCH ?= YES
|
||||||
USE_SSL ?= NO
|
USE_SSL ?= NO
|
||||||
USE_BIGENDIAN ?= AUTO
|
USE_BIGENDIAN ?= AUTO
|
||||||
BITS ?= AUTO
|
BITS ?= AUTO
|
||||||
SILENT ?= YES
|
SILENT ?= YES
|
||||||
|
LDLIBS += -levent
|
||||||
TERSE ?= NO
|
TERSE ?= NO
|
||||||
STACK_PROTECT ?= NO
|
STACK_PROTECT ?= NO
|
||||||
|
|
||||||
ifeq ($(OS), Windows_NT)
|
ifeq ($(OS), Windows_NT)
|
||||||
WINDOWS ?= YES
|
WINDOWS ?= YES
|
||||||
OPSYS ?= Windows
|
|
||||||
else
|
|
||||||
OPSYS ?= $(shell uname)
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(OPSYS),SunOS)
|
ifeq ($(WINDOWS),YES)
|
||||||
LDLIBS += -lsocket -lnsl
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(OPSYS),Haiku)
|
|
||||||
LDLIBS += -lnetwork
|
|
||||||
endif
|
|
||||||
|
|
||||||
CFLAGS += -I./src/
|
|
||||||
|
|
||||||
ifeq ($(OPSYS),Windows)
|
|
||||||
USE_BIGENDIAN := NO
|
USE_BIGENDIAN := NO
|
||||||
LDLIBS += -lws2_32
|
LDLIBS += -lws2_32
|
||||||
UHUB_CONF_DIR ?= c:/uhub/
|
UHUB_CONF_DIR ?= c:/uhub/
|
||||||
@@ -52,17 +39,20 @@ BIN_EXT ?=
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(SILENT),YES)
|
ifeq ($(SILENT),YES)
|
||||||
MSG_CC=@echo " CC:" $(notdir $<) &&
|
MSG_CC=@echo " CC:" $(notdir $^) &&
|
||||||
|
MSG_PCH=@echo " PCH:" $(notdir $@) &&
|
||||||
MSG_LD=@echo " LD:" $(notdir $@) &&
|
MSG_LD=@echo " LD:" $(notdir $@) &&
|
||||||
MSG_AR=@echo " AR:" $(notdir $@) &&
|
MSG_AR=@echo " AR:" $(notdir $@) &&
|
||||||
else
|
else
|
||||||
MSG_CC=
|
MSG_CC=
|
||||||
|
MSG_PCH=
|
||||||
MSG_LD=
|
MSG_LD=
|
||||||
MSG_AR=
|
MSG_AR=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(TERSE), YES)
|
ifeq ($(TERSE), YES)
|
||||||
MSG_CC=@
|
MSG_CC=@
|
||||||
|
MSG_PCH=@
|
||||||
MSG_LD=@
|
MSG_LD=@
|
||||||
MSG_AR=@
|
MSG_AR=@
|
||||||
MSG_CLEAN=-n ""
|
MSG_CLEAN=-n ""
|
||||||
@@ -70,10 +60,17 @@ else
|
|||||||
MSG_CLEAN="Clean as a whistle"
|
MSG_CLEAN="Clean as a whistle"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CFLAGS += -I/source/libevent
|
||||||
|
LDFLAGS += -L/source/libevent
|
||||||
|
|
||||||
|
-include release_setup.mk
|
||||||
ifeq ($(RELEASE),YES)
|
ifeq ($(RELEASE),YES)
|
||||||
CFLAGS += -O3 -DNDEBUG
|
CFLAGS += -Os -DNDEBUG
|
||||||
else
|
else
|
||||||
CFLAGS += -ggdb -DDEBUG
|
CFLAGS += -g -DDEBUG
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(STACK_PROTECT),YES)
|
ifeq ($(STACK_PROTECT),YES)
|
||||||
@@ -91,6 +88,13 @@ CFLAGS += -finstrument-functions
|
|||||||
CFLAGS += -DDEBUG_FUNCTION_TRACE
|
CFLAGS += -DDEBUG_FUNCTION_TRACE
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(USE_PCH),YES)
|
||||||
|
PCHSRC=src/uhub.h
|
||||||
|
PCH=src/uhub.h.gch
|
||||||
|
else
|
||||||
|
PCH=
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq ($(BITS), AUTO)
|
ifneq ($(BITS), AUTO)
|
||||||
ifeq ($(BITS), 64)
|
ifeq ($(BITS), 64)
|
||||||
CFLAGS += -m64
|
CFLAGS += -m64
|
||||||
@@ -118,122 +122,125 @@ CFLAGS += -DSSL_SUPPORT
|
|||||||
LDLIBS += -lssl
|
LDLIBS += -lssl
|
||||||
endif
|
endif
|
||||||
|
|
||||||
GIT_VERSION=$(shell git describe --tags 2>/dev/null || echo "")
|
ifneq ($(LIBEVENT_PATH),)
|
||||||
GIT_REVISION=$(shell git show --abbrev-commit 2>/dev/null | head -n 1 | cut -f 2 -d " " || echo "")
|
CFLAGS += -I$(LIBEVENT_PATH)
|
||||||
OLD_REVISION=$(shell grep GIT_REVISION revision.h 2>/dev/null | cut -f 3 -d " " | tr -d "\"")
|
LDFLAGS += -L$(LIBEVENT_PATH)
|
||||||
|
endif
|
||||||
|
|
||||||
# Sources
|
# Sources
|
||||||
libuhub_SOURCES := \
|
libuhub_SOURCES := \
|
||||||
src/core/auth.c \
|
src/auth.c \
|
||||||
src/core/commands.c \
|
src/commands.c \
|
||||||
src/core/config.c \
|
src/config.c \
|
||||||
src/core/eventqueue.c \
|
src/eventqueue.c \
|
||||||
src/core/hub.c \
|
src/hubevent.c \
|
||||||
src/core/hubevent.c \
|
src/hub.c \
|
||||||
src/core/hubio.c \
|
src/inf.c \
|
||||||
src/core/inf.c \
|
src/ipcalc.c \
|
||||||
src/core/netevent.c \
|
src/list.c \
|
||||||
src/core/probe.c \
|
src/log.c \
|
||||||
src/core/route.c \
|
src/memory.c \
|
||||||
src/core/user.c \
|
src/message.c \
|
||||||
src/core/usermanager.c \
|
src/misc.c \
|
||||||
src/network/backend.c \
|
src/netevent.c \
|
||||||
src/network/connection.c \
|
src/network.c \
|
||||||
src/network/epoll.c \
|
src/rbtree.c \
|
||||||
src/network/kqueue.c \
|
src/route.c \
|
||||||
src/network/network.c \
|
src/sid.c \
|
||||||
src/network/select.c \
|
src/tiger.c \
|
||||||
src/network/timeout.c \
|
src/user.c \
|
||||||
src/network/timer.c \
|
src/usermanager.c
|
||||||
src/util/ipcalc.c \
|
|
||||||
src/util/list.c \
|
|
||||||
src/util/log.c \
|
|
||||||
src/util/memory.c \
|
|
||||||
src/util/misc.c \
|
|
||||||
src/util/rbtree.c \
|
|
||||||
src/util/tiger.c
|
|
||||||
|
|
||||||
libadc_common_SOURCES := \
|
uhub_SOURCES := src/main.c
|
||||||
src/adc/message.c \
|
|
||||||
src/adc/sid.c
|
|
||||||
|
|
||||||
libadc_client_SOURCES := \
|
adcrush_SOURCES := src/adcrush.c
|
||||||
src/tools/adcclient.c
|
|
||||||
|
|
||||||
uhub_SOURCES := src/core/main.c
|
uhub_HEADERS := \
|
||||||
|
src/adcconst.h \
|
||||||
adcrush_SOURCES := src/tools/adcrush.c
|
src/auth.h \
|
||||||
|
src/config.h \
|
||||||
admin_SOURCES := src/tools/admin.c
|
src/eventid.h \
|
||||||
|
src/eventqueue.h \
|
||||||
|
src/hubevent.h \
|
||||||
|
src/hub.h \
|
||||||
|
src/inf.h \
|
||||||
|
src/ipcalc.h \
|
||||||
|
src/list.h \
|
||||||
|
src/log.h \
|
||||||
|
src/memory.h \
|
||||||
|
src/message.h \
|
||||||
|
src/misc.h \
|
||||||
|
src/netevent.h \
|
||||||
|
src/network.h \
|
||||||
|
src/rbtree.h \
|
||||||
|
src/route.h \
|
||||||
|
src/sid.h \
|
||||||
|
src/tiger.h \
|
||||||
|
src/uhub.h \
|
||||||
|
src/user.h \
|
||||||
|
src/usermanager.h
|
||||||
|
|
||||||
autotest_SOURCES := \
|
autotest_SOURCES := \
|
||||||
autotest/test_eventqueue.tcc \
|
autotest/test_message.tcc \
|
||||||
autotest/test_hub.tcc \
|
|
||||||
autotest/test_inf.tcc \
|
|
||||||
autotest/test_ipfilter.tcc \
|
|
||||||
autotest/test_list.tcc \
|
autotest/test_list.tcc \
|
||||||
autotest/test_memory.tcc \
|
autotest/test_memory.tcc \
|
||||||
autotest/test_message.tcc \
|
autotest/test_ipfilter.tcc \
|
||||||
|
autotest/test_inf.tcc \
|
||||||
|
autotest/test_hub.tcc \
|
||||||
autotest/test_misc.tcc \
|
autotest/test_misc.tcc \
|
||||||
autotest/test_sid.tcc \
|
|
||||||
autotest/test_tiger.tcc \
|
autotest/test_tiger.tcc \
|
||||||
autotest/test_timer.tcc \
|
autotest/test_usermanager.tcc \
|
||||||
autotest/test_usermanager.tcc
|
autotest/test_eventqueue.tcc
|
||||||
|
|
||||||
autotest_OBJECTS = autotest.o
|
autotest_OBJECTS = autotest.o
|
||||||
|
|
||||||
# Source to objects
|
# Source to objects
|
||||||
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
|
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
|
||||||
libadc_client_OBJECTS := $(libadc_client_SOURCES:.c=.o)
|
|
||||||
libadc_common_OBJECTS := $(libadc_common_SOURCES:.c=.o)
|
|
||||||
|
|
||||||
uhub_OBJECTS := $(uhub_SOURCES:.c=.o)
|
uhub_OBJECTS := $(uhub_SOURCES:.c=.o)
|
||||||
adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
|
adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
|
||||||
admin_OBJECTS := $(admin_SOURCES:.c=.o)
|
|
||||||
|
|
||||||
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS) $(admin_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS)
|
||||||
|
|
||||||
|
LIBUHUB=libuhub.a
|
||||||
uhub_BINARY=uhub$(BIN_EXT)
|
uhub_BINARY=uhub$(BIN_EXT)
|
||||||
adcrush_BINARY=adcrush$(BIN_EXT)
|
adcrush_BINARY=adcrush$(BIN_EXT)
|
||||||
admin_BINARY=uhub-admin$(BIN_EXT)
|
|
||||||
autotest_BINARY=autotest/test$(BIN_EXT)
|
autotest_BINARY=autotest/test$(BIN_EXT)
|
||||||
|
|
||||||
.PHONY: revision.h.tmp
|
%.o: %.c
|
||||||
|
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@.tmp $^ && \
|
||||||
|
$(MV) $@.tmp $@
|
||||||
|
|
||||||
%.o: %.c version.h revision.h
|
all: $(uhub_BINARY) $(PCH)
|
||||||
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@ $<
|
|
||||||
|
|
||||||
all: $(uhub_BINARY)
|
$(adcrush_BINARY): $(PCH) $(LIBUHUB) $(adcrush_OBJECTS)
|
||||||
|
$(MSG_LD) $(CC) -o $@.tmp $(adcrush_OBJECTS) $(LIBUHUB) $(LDFLAGS) $(LDLIBS) && \
|
||||||
|
$(MV) $@.tmp $@
|
||||||
|
|
||||||
$(adcrush_BINARY): $(adcrush_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
$(uhub_BINARY): $(PCH) $(LIBUHUB) $(uhub_OBJECTS)
|
||||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
$(MSG_LD) $(CC) -o $@.tmp $(uhub_OBJECTS) $(LIBUHUB) $(LDFLAGS) $(LDLIBS) && \
|
||||||
|
$(MV) $@.tmp $@
|
||||||
|
|
||||||
$(admin_BINARY): $(admin_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
$(LIBUHUB): $(libuhub_OBJECTS)
|
||||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
$(MSG_AR) $(AR) rc $@.tmp $^ && \
|
||||||
|
$(RANLIB) $@.tmp && \
|
||||||
|
$(MV) $@.tmp $@
|
||||||
|
|
||||||
$(uhub_BINARY): $(uhub_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS)
|
ifeq ($(USE_PCH),YES)
|
||||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
$(PCH): $(uhub_HEADERS)
|
||||||
|
$(MSG_PCH) $(CC) $(CFLAGS) -o $@.tmp $(PCHSRC) && \
|
||||||
|
$(MV) $@.tmp $@
|
||||||
|
endif
|
||||||
|
|
||||||
autotest.c: $(autotest_SOURCES)
|
autotest.c: $(autotest_SOURCES)
|
||||||
$(shell exotic --standalone $(autotest_SOURCES) > $@)
|
$(shell exotic --standalone $(autotest_SOURCES) > $@)
|
||||||
|
|
||||||
revision.h.tmp:
|
|
||||||
@rm -f $@
|
|
||||||
@echo "/* AUTOGENERATED FILE - DO NOT EDIT */" > $@
|
|
||||||
@if [ -n '$(GIT_VERSION)' ]; then echo \#define GIT_VERSION \"$(GIT_VERSION)\" >> $@; fi
|
|
||||||
@if [ -n '$(GIT_REVISION)' ]; then echo \#define GIT_REVISION \"$(GIT_REVISION)\" >> $@; fi
|
|
||||||
|
|
||||||
version.h: revision.h
|
|
||||||
|
|
||||||
revision.h: revision.h.tmp
|
|
||||||
@if [ '$(GIT_REVISION)' != '$(OLD_REVISION)' ]; then cp $@.tmp $@; fi
|
|
||||||
@if [ ! -f $@ ]; then cp $@.tmp $@; fi
|
|
||||||
|
|
||||||
$(autotest_OBJECTS): autotest.c
|
$(autotest_OBJECTS): autotest.c
|
||||||
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@ $<
|
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@.tmp $< && \
|
||||||
|
$(MV) $@.tmp $@
|
||||||
|
|
||||||
$(autotest_BINARY): $(autotest_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
$(autotest_BINARY): $(autotest_OBJECTS) $(LIBUHUB)
|
||||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
$(MSG_LD) $(CC) -o $@.tmp $^ $(LDFLAGS) $(LDLIBS) && \
|
||||||
|
$(MV) $@.tmp $@
|
||||||
|
|
||||||
autotest: $(autotest_BINARY)
|
autotest: $(autotest_BINARY)
|
||||||
@./$(autotest_BINARY) -s -f
|
@./$(autotest_BINARY) -s -f
|
||||||
@@ -253,10 +260,11 @@ install: $(uhub_BINARY)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
dist-clean:
|
dist-clean:
|
||||||
@rm -rf $(all_OBJECTS) *~ core
|
@rm -rf $(all_OBJECTS) $(PCH) *~ core
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -rf $(libuhub_OBJECTS) *~ core $(uhub_BINARY) $(admin_BINARY) $(autotest_BINARY) $(adcrush_BINARY) $(all_OBJECTS) autotest.c revision.h revision.h.tmp && \
|
@rm -rf $(libuhub_OBJECTS) $(PCH) *~ core $(uhub_BINARY) $(LIBUHUB) $(all_OBJECTS) && \
|
||||||
echo $(MSG_CLEAN)
|
echo $(MSG_CLEAN)
|
||||||
|
|
||||||
|
-include release_targets.mk
|
||||||
|
|
||||||
|
|||||||
5
README
5
README
@@ -1,8 +1,5 @@
|
|||||||
Welcome and thanks for downloading uHub, a high performance ADC p2p hub.
|
Welcome and thanks for downloading uHub, a high performance ADC p2p hub.
|
||||||
|
|
||||||
For the official documentation, bugs and other information, please visit:
|
For the official documentation, bugs and other information, please visit:
|
||||||
http://www.uhub.org/
|
http://www.extatic.org/uhub/
|
||||||
|
|
||||||
For a list of compatible ADC clients, see:
|
|
||||||
http://www.adcportal.com/wiki/index.php/ADC_Software_List#Client_Software
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ static void create_test_user()
|
|||||||
if (g_user)
|
if (g_user)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_user = (struct hub_user*) malloc(sizeof(struct hub_user));
|
g_user = (struct user*) malloc(sizeof(struct user));
|
||||||
memset(g_user, 0, sizeof(struct hub_user));
|
memset(g_user, 0, sizeof(struct user));
|
||||||
memcpy(g_user->id.nick, "exotic-tester", 13);
|
memcpy(g_user->id.nick, "exotic-tester", 13);
|
||||||
g_user->sid = 1;
|
g_user->sid = 1;
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,6 @@ EXO_TEST(hub_net_startup, {
|
|||||||
|
|
||||||
EXO_TEST(hub_config_initialize, {
|
EXO_TEST(hub_config_initialize, {
|
||||||
config_defaults(&g_config);
|
config_defaults(&g_config);
|
||||||
g_config.server_port = 65111;
|
|
||||||
return 1;
|
return 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -68,5 +67,5 @@ EXO_TEST(hub_service_shutdown, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(hub_net_shutdown, {
|
EXO_TEST(hub_net_shutdown, {
|
||||||
return (net_destroy() != -1);
|
return (net_shutdown() != -1);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,17 +5,17 @@
|
|||||||
#define USER_NICK "Friend"
|
#define USER_NICK "Friend"
|
||||||
#define USER_SID "AAAB"
|
#define USER_SID "AAAB"
|
||||||
|
|
||||||
static struct hub_user* inf_user = 0;
|
static struct user* inf_user = 0;
|
||||||
static struct hub_info* inf_hub = 0;
|
static struct hub_info* inf_hub = 0;
|
||||||
|
|
||||||
extern int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd);
|
extern int hub_handle_info_login(struct hub_info* hub, struct user* user, struct adc_message* cmd);
|
||||||
|
|
||||||
static void inf_create_hub()
|
static void inf_create_hub()
|
||||||
{
|
{
|
||||||
inf_hub = (struct hub_info*) hub_malloc_zero(sizeof(struct hub_info));
|
inf_hub = (struct hub_info*) hub_malloc_zero(sizeof(struct hub_info));
|
||||||
inf_hub->users = (struct hub_user_manager*) hub_malloc_zero(sizeof(struct hub_user_manager));
|
inf_hub->users = (struct user_manager*) hub_malloc_zero(sizeof(struct user_manager));
|
||||||
inf_hub->users->list = list_create();
|
inf_hub->users->list = list_create();
|
||||||
inf_hub->users->sids = sid_pool_create(500);
|
inf_hub->users->free_sid = 1;
|
||||||
|
|
||||||
inf_hub->acl = (struct acl_handle*) hub_malloc_zero(sizeof(struct acl_handle));
|
inf_hub->acl = (struct acl_handle*) hub_malloc_zero(sizeof(struct acl_handle));
|
||||||
inf_hub->config = (struct hub_config*) hub_malloc_zero(sizeof(struct hub_config));
|
inf_hub->config = (struct hub_config*) hub_malloc_zero(sizeof(struct hub_config));
|
||||||
@@ -28,7 +28,6 @@ static void inf_destroy_hub()
|
|||||||
{
|
{
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
list_destroy(inf_hub->users->list);
|
list_destroy(inf_hub->users->list);
|
||||||
sid_pool_destroy(inf_hub->users->sids);
|
|
||||||
acl_shutdown(inf_hub->acl);
|
acl_shutdown(inf_hub->acl);
|
||||||
free_config(inf_hub->config);
|
free_config(inf_hub->config);
|
||||||
hub_free(inf_hub->users);
|
hub_free(inf_hub->users);
|
||||||
@@ -41,8 +40,9 @@ static void inf_destroy_hub()
|
|||||||
static void inf_create_user()
|
static void inf_create_user()
|
||||||
{
|
{
|
||||||
if (inf_user) return;
|
if (inf_user) return;
|
||||||
inf_user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
|
inf_user = (struct user*) hub_malloc_zero(sizeof(struct user));
|
||||||
inf_user->id.sid = 1;
|
inf_user->id.sid = 1;
|
||||||
|
inf_user->sd = -1;
|
||||||
inf_user->limits.upload_slots = 1;
|
inf_user->limits.upload_slots = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ static struct ip_addr_encap ip6_a;
|
|||||||
static struct ip_addr_encap ip6_b;
|
static struct ip_addr_encap ip6_b;
|
||||||
static struct ip_addr_encap ip6_c;
|
static struct ip_addr_encap ip6_c;
|
||||||
static struct ip_addr_encap mask;
|
static struct ip_addr_encap mask;
|
||||||
static struct ip_range ban6;
|
static struct ip_ban_record ban6;
|
||||||
static struct ip_range ban4;
|
static struct ip_ban_record ban4;
|
||||||
|
|
||||||
EXO_TEST(prepare_network, {
|
EXO_TEST(prepare_network, {
|
||||||
return net_initialize() == 0;
|
return net_initialize() == 0;
|
||||||
@@ -405,74 +405,74 @@ EXO_TEST(check_ban_setup_1, {
|
|||||||
|
|
||||||
EXO_TEST(check_ban_ipv4_1, {
|
EXO_TEST(check_ban_ipv4_1, {
|
||||||
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.0", &addr);
|
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.0", &addr);
|
||||||
return ip_in_range(&addr, &ban4);
|
return acl_check_ip_range(&addr, &ban4);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_ipv4_2, {
|
EXO_TEST(check_ban_ipv4_2, {
|
||||||
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.1", &addr);
|
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.1", &addr);
|
||||||
return ip_in_range(&addr, &ban4);
|
return acl_check_ip_range(&addr, &ban4);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_ipv4_3, {
|
EXO_TEST(check_ban_ipv4_3, {
|
||||||
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.255", &addr);
|
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.255", &addr);
|
||||||
return ip_in_range(&addr, &ban4);
|
return acl_check_ip_range(&addr, &ban4);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_ipv4_4, {
|
EXO_TEST(check_ban_ipv4_4, {
|
||||||
struct ip_addr_encap addr; ip_convert_to_binary("192.168.1.0", &addr);
|
struct ip_addr_encap addr; ip_convert_to_binary("192.168.1.0", &addr);
|
||||||
return !ip_in_range(&addr, &ban4);
|
return !acl_check_ip_range(&addr, &ban4);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_ipv4_5, {
|
EXO_TEST(check_ban_ipv4_5, {
|
||||||
struct ip_addr_encap addr; ip_convert_to_binary("192.167.255.255", &addr);
|
struct ip_addr_encap addr; ip_convert_to_binary("192.167.255.255", &addr);
|
||||||
return !ip_in_range(&addr, &ban4);
|
return !acl_check_ip_range(&addr, &ban4);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_ipv6_1, {
|
EXO_TEST(check_ban_ipv6_1, {
|
||||||
if (!ipv6) return 1;
|
if (!ipv6) return 1;
|
||||||
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:0", &addr);
|
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:0", &addr);
|
||||||
return ip_in_range(&addr, &ban6);
|
return acl_check_ip_range(&addr, &ban6);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_ipv6_2, {
|
EXO_TEST(check_ban_ipv6_2, {
|
||||||
if (!ipv6) return 1;
|
if (!ipv6) return 1;
|
||||||
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:1", &addr);
|
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:1", &addr);
|
||||||
return ip_in_range(&addr, &ban6);
|
return acl_check_ip_range(&addr, &ban6);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_ipv6_3, {
|
EXO_TEST(check_ban_ipv6_3, {
|
||||||
if (!ipv6) return 1;
|
if (!ipv6) return 1;
|
||||||
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:fffe", &addr);
|
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:fffe", &addr);
|
||||||
return ip_in_range(&addr, &ban6);
|
return acl_check_ip_range(&addr, &ban6);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_ipv6_4, {
|
EXO_TEST(check_ban_ipv6_4, {
|
||||||
if (!ipv6) return 1;
|
if (!ipv6) return 1;
|
||||||
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:ffff", &addr);
|
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:ffff", &addr);
|
||||||
return ip_in_range(&addr, &ban6);
|
return acl_check_ip_range(&addr, &ban6);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_ipv6_5, {
|
EXO_TEST(check_ban_ipv6_5, {
|
||||||
if (!ipv6) return 1;
|
if (!ipv6) return 1;
|
||||||
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefb:0", &addr);
|
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefb:0", &addr);
|
||||||
return !ip_in_range(&addr, &ban6);
|
return !acl_check_ip_range(&addr, &ban6);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_ipv6_6, {
|
EXO_TEST(check_ban_ipv6_6, {
|
||||||
if (!ipv6) return 1;
|
if (!ipv6) return 1;
|
||||||
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
|
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
|
||||||
return !ip_in_range(&addr, &ban6);
|
return !acl_check_ip_range(&addr, &ban6);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_afmix_1, {
|
EXO_TEST(check_ban_afmix_1, {
|
||||||
if (!ipv6) return 1;
|
if (!ipv6) return 1;
|
||||||
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
|
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
|
||||||
return !ip_in_range(&addr, &ban4);
|
return !acl_check_ip_range(&addr, &ban4);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_afmix_2, {
|
EXO_TEST(check_ban_afmix_2, {
|
||||||
struct ip_addr_encap addr; ip_convert_to_binary("10.20.30.40", &addr);
|
struct ip_addr_encap addr; ip_convert_to_binary("10.20.30.40", &addr);
|
||||||
return !ip_in_range(&addr, &ban6);
|
return !acl_check_ip_range(&addr, &ban6);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(ip4_bitwise_AND_1, {
|
EXO_TEST(ip4_bitwise_AND_1, {
|
||||||
@@ -594,28 +594,6 @@ EXO_TEST(ip6_bitwise_OR_3, {
|
|||||||
return !strcmp(ip_convert_to_string(&ip6_c), "7777:cccc:3333:1111:ffff:ffff:ffff:1c1c");
|
return !strcmp(ip_convert_to_string(&ip6_c), "7777:cccc:3333:1111:ffff:ffff:ffff:1c1c");
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(ip_range_1, {
|
|
||||||
struct ip_range range; memset(&range, 0, sizeof(range));
|
|
||||||
return ip_convert_address_to_range("192.168.0.1", &range) && memcmp(&range.lo, &range.hi, sizeof(struct ip_addr_encap)) == 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(ip_range_2, {
|
|
||||||
struct ip_range range; memset(&range, 0, sizeof(range));
|
|
||||||
return ip_convert_address_to_range("192.168.0.0-192.168.255.255", &range) && range.lo.af == range.hi.af && memcmp(&range.lo, &range.hi, sizeof(struct ip_addr_encap)) != 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(ip_range_3, {
|
|
||||||
struct ip_range range; memset(&range, 0, sizeof(range));
|
|
||||||
return ip_convert_address_to_range("192.168.0.0/16", &range) && range.lo.af == range.hi.af && memcmp(&range.lo, &range.hi, sizeof(struct ip_addr_encap)) != 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(ip_range_4, {
|
|
||||||
struct ip_range range1; memset(&range1, 0, sizeof(range1));
|
|
||||||
struct ip_range range2; memset(&range2, 0, sizeof(range2));
|
|
||||||
return ip_convert_address_to_range("192.168.0.0/16", &range1) && ip_convert_address_to_range("192.168.0.0-192.168.255.255", &range2) && memcmp(&range1, &range2, sizeof(struct ip_range)) == 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
EXO_TEST(shutdown_network, {
|
EXO_TEST(shutdown_network, {
|
||||||
return net_destroy() == 0;
|
return net_shutdown() == 0;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,27 +8,27 @@ EXO_TEST(test_message_refc_1, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_2, {
|
EXO_TEST(test_message_refc_2, {
|
||||||
return g_msg->references == 1;
|
return g_msg->references == 0; // 0
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_3, {
|
EXO_TEST(test_message_refc_3, {
|
||||||
adc_msg_incref(g_msg);
|
adc_msg_incref(g_msg);
|
||||||
return g_msg->references == 2;
|
return g_msg->references == 1; // 1
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_4, {
|
EXO_TEST(test_message_refc_4, {
|
||||||
adc_msg_incref(g_msg);
|
adc_msg_incref(g_msg);
|
||||||
return g_msg->references == 3;
|
return g_msg->references == 2; // 2
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_5, {
|
EXO_TEST(test_message_refc_5, {
|
||||||
adc_msg_free(g_msg);
|
adc_msg_free(g_msg);
|
||||||
return g_msg->references == 2;
|
return g_msg->references == 1; // 1
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_6, {
|
EXO_TEST(test_message_refc_6, {
|
||||||
adc_msg_free(g_msg);
|
adc_msg_free(g_msg);
|
||||||
return g_msg->references == 1;
|
return g_msg->references == 0; // 0
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_7, {
|
EXO_TEST(test_message_refc_7, {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include <uhub.h>
|
#include <uhub.h>
|
||||||
static struct hub_user* g_user = 0;
|
static struct user* g_user = 0;
|
||||||
static const char* test_string1 = "IINF AAfoo BBbar CCwhat\n";
|
static const char* test_string1 = "IINF AAfoo BBbar CCwhat\n";
|
||||||
static const char* test_string2 = "BMSG AAAB Hello\\sWorld!\n";
|
static const char* test_string2 = "BMSG AAAB Hello\\sWorld!\n";
|
||||||
static const char* test_string3 = "BINF AAAB IDAN7ZMSLIEBL53OPTM7WXGSTXUS3XOY6KQS5LBGX NIFriend DEstuff SL3 SS0 SF0 VEQuickDC/0.4.17 US6430 SUADC0,TCP4,UDP4 I4127.0.0.1 HO5 HN1 AW\n";
|
static const char* test_string3 = "BINF AAAB IDAN7ZMSLIEBL53OPTM7WXGSTXUS3XOY6KQS5LBGX NIFriend DEstuff SL3 SS0 SF0 VEQuickDC/0.4.17 US6430 SUADC0,TCP4,UDP4 I4127.0.0.1 HO5 HN1 AW\n";
|
||||||
@@ -11,8 +11,8 @@ static void create_test_user()
|
|||||||
if (g_user)
|
if (g_user)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_user = (struct hub_user*) malloc(sizeof(struct hub_user));
|
g_user = (struct user*) malloc(sizeof(struct user));
|
||||||
memset(g_user, 0, sizeof(struct hub_user));
|
memset(g_user, 0, sizeof(struct user));
|
||||||
memcpy(g_user->id.nick, "exotic-tester", 13);
|
memcpy(g_user->id.nick, "exotic-tester", 13);
|
||||||
g_user->id.sid = 1;
|
g_user->id.sid = 1;
|
||||||
}
|
}
|
||||||
@@ -31,9 +31,7 @@ EXO_TEST(adc_message_parse_1, {
|
|||||||
|
|
||||||
EXO_TEST(adc_message_parse_2, {
|
EXO_TEST(adc_message_parse_2, {
|
||||||
struct adc_message* msg = adc_msg_create(test_string2);
|
struct adc_message* msg = adc_msg_create(test_string2);
|
||||||
int ok = (msg != NULL);
|
return msg == NULL;
|
||||||
adc_msg_free(msg);
|
|
||||||
return ok;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_parse_3, {
|
EXO_TEST(adc_message_parse_3, {
|
||||||
|
|||||||
@@ -1,138 +0,0 @@
|
|||||||
#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;
|
|
||||||
});
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
#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;
|
|
||||||
});
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
#include <uhub.h>
|
|
||||||
|
|
||||||
#define MAX_USERS 64
|
|
||||||
|
|
||||||
static struct hub_info um_hub;
|
|
||||||
static struct hub_user um_user[MAX_USERS];
|
|
||||||
// static struct net_connection um_cons[MAX_USERS];
|
|
||||||
|
|
||||||
EXO_TEST(um_test_setup, {
|
|
||||||
int i = 0;
|
|
||||||
memset(&um_hub, 0, sizeof(um_hub));
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_USERS; i++)
|
|
||||||
{
|
|
||||||
/* memset(&um_cons[i], 0, sizeof(struct net_connection));
|
|
||||||
um_cons[i].sd = -1;
|
|
||||||
|
|
||||||
memset(&um_user[i], 0, sizeof(struct hub_user));
|
|
||||||
um_user[i].id.sid = i+1;
|
|
||||||
um_user[i].connection = &um_cons[i];*/
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(um_init_1, {
|
|
||||||
return uman_init(0) != 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(um_init_2, {
|
|
||||||
return uman_init(&um_hub) == 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(um_shutdown_1, {
|
|
||||||
return uman_shutdown(0) == -1;
|
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(um_shutdown_2, {
|
|
||||||
return uman_shutdown(&um_hub) == 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(um_shutdown_3, {
|
|
||||||
return uman_shutdown(&um_hub) == -1;
|
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(um_init_3, {
|
|
||||||
return uman_init(&um_hub) == 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(um_add_1, {
|
|
||||||
return uman_add(&um_hub, &um_user[0]) == 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(um_size_1, {
|
|
||||||
return hub_get_user_count(&um_hub) == 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
EXO_TEST(um_remove_1, {
|
|
||||||
return uman_remove(&um_hub, &um_user[0]) == 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(um_size_2, {
|
|
||||||
return hub_get_user_count(&um_hub) == 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
EXO_TEST(um_add_2, {
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < MAX_USERS; i++)
|
|
||||||
{
|
|
||||||
if (uman_add(&um_hub, &um_user[i]) != 0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(um_size_3, {
|
|
||||||
return hub_get_user_count(&um_hub) == MAX_USERS;
|
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(um_add_3, {
|
|
||||||
return uman_add(&um_hub, &um_user[5]) != 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(um_remove_2, {
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < MAX_USERS; i++)
|
|
||||||
{
|
|
||||||
if (uman_remove(&um_hub, &um_user[i]) != 0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Last test */
|
|
||||||
EXO_TEST(um_shutdown_4, {
|
|
||||||
return uman_shutdown(&um_hub) == 0;
|
|
||||||
});
|
|
||||||
13
debian/changelog
vendored
13
debian/changelog
vendored
@@ -1,13 +0,0 @@
|
|||||||
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
1
debian/compat
vendored
@@ -1 +0,0 @@
|
|||||||
7
|
|
||||||
24
debian/control
vendored
24
debian/control
vendored
@@ -1,24 +0,0 @@
|
|||||||
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
19
debian/copyright
vendored
@@ -1,19 +0,0 @@
|
|||||||
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
45
debian/rules
vendored
@@ -1,45 +0,0 @@
|
|||||||
#!/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
4
debian/uhub.default
vendored
@@ -1,4 +0,0 @@
|
|||||||
# uhub - high performance adc hub.
|
|
||||||
|
|
||||||
UHUB_ENABLE=0
|
|
||||||
|
|
||||||
6
debian/uhub.dirs
vendored
6
debian/uhub.dirs
vendored
@@ -1,6 +0,0 @@
|
|||||||
etc/default
|
|
||||||
etc/init.d
|
|
||||||
etc/logrotate.d
|
|
||||||
etc/uhub
|
|
||||||
usr/bin
|
|
||||||
var/log/uhub
|
|
||||||
5
debian/uhub.docs
vendored
5
debian/uhub.docs
vendored
@@ -1,5 +0,0 @@
|
|||||||
AUTHORS
|
|
||||||
README
|
|
||||||
BUGS
|
|
||||||
TODO
|
|
||||||
doc/getstarted.txt
|
|
||||||
92
debian/uhub.init
vendored
92
debian/uhub.init
vendored
@@ -1,92 +0,0 @@
|
|||||||
#!/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
9
debian/uhub.logrotate
vendored
@@ -1,9 +0,0 @@
|
|||||||
/var/log/uhub/*.log
|
|
||||||
{
|
|
||||||
compress
|
|
||||||
size 10M
|
|
||||||
rotate 10
|
|
||||||
missingok
|
|
||||||
notifempty
|
|
||||||
}
|
|
||||||
|
|
||||||
1
debian/uhub.manpages
vendored
1
debian/uhub.manpages
vendored
@@ -1 +0,0 @@
|
|||||||
doc/uhub.1
|
|
||||||
27
debian/uhub.postinst
vendored
27
debian/uhub.postinst
vendored
@@ -1,27 +0,0 @@
|
|||||||
#!/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
6
debian/uhub.postrm
vendored
@@ -1,6 +0,0 @@
|
|||||||
#!/bin/sh -e
|
|
||||||
|
|
||||||
if [ "$1" = purge ]; then
|
|
||||||
update-rc.d uhub remove >/dev/null
|
|
||||||
fi
|
|
||||||
|
|
||||||
10
debian/uhub.prerm
vendored
10
debian/uhub.prerm
vendored
@@ -1,10 +0,0 @@
|
|||||||
#!/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,13 +8,19 @@ Prerequisites
|
|||||||
Before you try to compile µHub, please make sure the following prerequisites are met.
|
Before you try to compile µHub, please make sure the following prerequisites are met.
|
||||||
* GNU make
|
* GNU make
|
||||||
* gcc > 3.0 (or MinGW on Windows)
|
* gcc > 3.0 (or MinGW on Windows)
|
||||||
|
* libevent >= 1.3
|
||||||
* Perl 5
|
* Perl 5
|
||||||
|
|
||||||
Linux, Mac OSX, FreeBSD, NetBSD and OpenBSD
|
Linux and Mac OSX
|
||||||
-------------------------------------------
|
-----------------
|
||||||
Simply, run:
|
Simply, run:
|
||||||
% make
|
% make
|
||||||
|
|
||||||
|
FreeBSD, NetBSD and OpenBSD
|
||||||
|
---------------------------
|
||||||
|
Use GNU make, not BSD make:
|
||||||
|
% gmake
|
||||||
|
|
||||||
If you have an old gcc compiler, try disabling pre-compiled headers like this:
|
If you have an old gcc compiler, try disabling pre-compiled headers like this:
|
||||||
gmake USE_PCH=NO
|
gmake USE_PCH=NO
|
||||||
|
|
||||||
|
|||||||
@@ -43,15 +43,4 @@ if one wishes to run uhub as a specific user using the -u and -g switches.
|
|||||||
Example:
|
Example:
|
||||||
% uhub -f -l mylog.txt -u nobody -g nogroup
|
% uhub -f -l mylog.txt -u nobody -g nogroup
|
||||||
|
|
||||||
|
|
||||||
If you are planning to more than 1024 users on hub, you must increase the max number of file descriptors allowed.
|
|
||||||
This limit needs to be higher than the configured max_users in uhub.conf.
|
|
||||||
|
|
||||||
In linux can add the following lines to /etc/security/limits.conf (allows for ~4000 users)
|
|
||||||
* soft nofile 4096
|
|
||||||
* hard nofile 4096
|
|
||||||
|
|
||||||
Or, you can use (as root):
|
|
||||||
% ulimit -n 4096
|
|
||||||
|
|
||||||
Your mileage may vary -- Good luck!
|
Your mileage may vary -- Good luck!
|
||||||
|
|||||||
@@ -1,101 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
#
|
|
||||||
# chkconfig: - 91 35
|
|
||||||
# description: Starts and stops the Uhub ( http://www.extatic.org/uhub ) daemons on RHEL\CentOS \
|
|
||||||
# used to provide p2p network services.
|
|
||||||
#
|
|
||||||
# pidfile: /var/run/uhub.pid
|
|
||||||
# config: /etc/uhub/uhub.conf
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Source function library.
|
|
||||||
if [ -f /etc/init.d/functions ] ; then
|
|
||||||
. /etc/init.d/functions
|
|
||||||
elif [ -f /etc/rc.d/init.d/functions ] ; then
|
|
||||||
. /etc/rc.d/init.d/functions
|
|
||||||
else
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Avoid using root's TMPDIR
|
|
||||||
unset TMPDIR
|
|
||||||
|
|
||||||
# Source networking configuration.
|
|
||||||
. /etc/sysconfig/network
|
|
||||||
|
|
||||||
if [ -f /etc/sysconfig/uhub ]; then
|
|
||||||
. /etc/sysconfig/uhub
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check that networking is up.
|
|
||||||
[ ${NETWORKING} = "no" ] && exit 1
|
|
||||||
|
|
||||||
# Check that uhub.conf exists.
|
|
||||||
[ -f /etc/uhub/uhub.conf ] || exit 6
|
|
||||||
|
|
||||||
RETVAL=0
|
|
||||||
|
|
||||||
|
|
||||||
start() {
|
|
||||||
KIND="Uhub"
|
|
||||||
echo -n $"Starting $KIND services: "
|
|
||||||
daemon uhub $UHUBOPTIONS
|
|
||||||
RETVAL=$?
|
|
||||||
echo ""
|
|
||||||
return $RETVAL
|
|
||||||
}
|
|
||||||
|
|
||||||
stop() {
|
|
||||||
KIND="Uhub"
|
|
||||||
echo -n $"Shutting down $KIND services: "
|
|
||||||
killproc uhub
|
|
||||||
RETVAL=$?
|
|
||||||
echo ""
|
|
||||||
return $RETVAL
|
|
||||||
}
|
|
||||||
|
|
||||||
restart() {
|
|
||||||
stop
|
|
||||||
start
|
|
||||||
}
|
|
||||||
|
|
||||||
reload() {
|
|
||||||
echo -n $"Reloading uhub.conf / user.conf file: "
|
|
||||||
killproc uhub -HUP
|
|
||||||
RETVAL=$?
|
|
||||||
echo ""
|
|
||||||
return $RETVAL
|
|
||||||
}
|
|
||||||
|
|
||||||
rhstatus() {
|
|
||||||
status uhub
|
|
||||||
RETVAL=$?
|
|
||||||
if [ $RETVAL -ne 0 ] ; then
|
|
||||||
return $RETVAL
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
start)
|
|
||||||
start
|
|
||||||
;;
|
|
||||||
stop)
|
|
||||||
stop
|
|
||||||
;;
|
|
||||||
restart)
|
|
||||||
restart
|
|
||||||
;;
|
|
||||||
reload)
|
|
||||||
reload
|
|
||||||
;;
|
|
||||||
status)
|
|
||||||
rhstatus
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo $"Usage: $0 {start|stop|restart|reload|status}"
|
|
||||||
exit 2
|
|
||||||
esac
|
|
||||||
|
|
||||||
exit $?
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
# Log rotate for Uhub
|
|
||||||
# see man logrotate
|
|
||||||
#
|
|
||||||
#
|
|
||||||
/var/log/uhub.log {
|
|
||||||
compress
|
|
||||||
size 10M
|
|
||||||
rotate 10
|
|
||||||
missingok
|
|
||||||
notifempty
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# Options to UHUB
|
|
||||||
# -v Verbose mode. Add more -v's for higher verbosity.
|
|
||||||
# -q Quiet mode - no output
|
|
||||||
# -f Fork to background
|
|
||||||
# -l <file> Log messages to given file (default: stderr)
|
|
||||||
# -L Log messages to syslog
|
|
||||||
# -c <file> Specify configuration file (default: /etc/uhub/uhub.conf)
|
|
||||||
# -S Show configuration parameters, but ignore defaults
|
|
||||||
# -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"
|
|
||||||
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
1. rule #1
|
|
||||||
2. rule #2
|
|
||||||
3. rule #3
|
|
||||||
......
|
|
||||||
34. Rule #34
|
|
||||||
@@ -4,8 +4,7 @@
|
|||||||
#
|
#
|
||||||
# This file is read only to the uhub deamon, and if you
|
# This file is read only to the uhub deamon, and if you
|
||||||
# make changes to it while uhub is running you can send a
|
# make changes to it while uhub is running you can send a
|
||||||
# HUP signal to it ( $ killall -HUP uhub ), to reparse configuration (only on UNIX).
|
# HUP signal to it, to reparse configuration (only on UNIX).
|
||||||
# All configuration directives: http://www.uhub.org/config.php
|
|
||||||
|
|
||||||
# Bind to this port and address
|
# Bind to this port and address
|
||||||
# server_bind_addr=any means listen to "::" if IPv6 is supported
|
# server_bind_addr=any means listen to "::" if IPv6 is supported
|
||||||
@@ -13,18 +12,12 @@
|
|||||||
server_port=1511
|
server_port=1511
|
||||||
server_bind_addr=any
|
server_bind_addr=any
|
||||||
|
|
||||||
# Alternative server ports
|
|
||||||
# server_alt_ports = 1512, 1513
|
|
||||||
|
|
||||||
# The maximum amount of users allowed on the hub.
|
# The maximum amount of users allowed on the hub.
|
||||||
max_users=500
|
max_users=500
|
||||||
|
|
||||||
# If 1, will show a "Powered by uHub/{VERSION}".
|
# If 1, will show a "This hub is running uhub/version".
|
||||||
show_banner=1
|
show_banner=1
|
||||||
|
|
||||||
# If enabled then operating system and cpu architecture is part of the banner.
|
|
||||||
show_banner_sys_info=1
|
|
||||||
|
|
||||||
# Allow only registered users on the hub if set to 1.
|
# Allow only registered users on the hub if set to 1.
|
||||||
registered_users_only=0
|
registered_users_only=0
|
||||||
|
|
||||||
@@ -45,35 +38,6 @@ file_acl=/etc/uhub/users.conf
|
|||||||
# Normally this message is sent to clients when connecting.
|
# Normally this message is sent to clients when connecting.
|
||||||
file_motd=/etc/uhub/motd.txt
|
file_motd=/etc/uhub/motd.txt
|
||||||
|
|
||||||
# This file can contain a rules of the hub.
|
|
||||||
# Normally this message is sent to clients when write in chat !rules
|
|
||||||
file_rules=/etc/uhub/rules.txt
|
|
||||||
|
|
||||||
|
|
||||||
# Slots\share\hubs limits
|
|
||||||
limit_max_hubs_user = 0
|
|
||||||
limit_max_hubs_reg = 0
|
|
||||||
limit_max_hubs_op = 0
|
|
||||||
limit_max_hubs = 0
|
|
||||||
limit_min_hubs_user = 0
|
|
||||||
limit_min_hubs_reg = 0
|
|
||||||
limit_min_hubs_op = 0
|
|
||||||
limit_min_share = 0
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# chat control
|
|
||||||
# if chat_is_privileged=yes only registered users may write in main chat
|
|
||||||
chat_is_privileged = no
|
|
||||||
|
|
||||||
# if chat_only = yes then search and transfer functionality is disabled for
|
|
||||||
# non-operator users.
|
|
||||||
chat_only = no
|
|
||||||
|
|
||||||
# Configure status message as sent to clients in different circumstances.
|
# Configure status message as sent to clients in different circumstances.
|
||||||
msg_hub_full = Hub is full
|
msg_hub_full = Hub is full
|
||||||
msg_hub_disabled = Hub is disabled
|
msg_hub_disabled = Hub is disabled
|
||||||
@@ -97,12 +61,6 @@ msg_ban_permanently = Banned permanently
|
|||||||
msg_ban_temporarily = Banned temporarily
|
msg_ban_temporarily = Banned temporarily
|
||||||
msg_auth_invalid_password = Password is wrong
|
msg_auth_invalid_password = Password is wrong
|
||||||
msg_auth_user_not_found = User not found in password database
|
msg_auth_user_not_found = User not found in password database
|
||||||
msg_user_share_size_low = User is not sharing enough
|
|
||||||
msg_user_share_size_high = User is sharing too much
|
|
||||||
msg_user_slots_low = User have too few upload slots
|
|
||||||
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_error_no_memory = No memory
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
# 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
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
Summary: High performance ADC p2p hub.
|
|
||||||
Name: uhub
|
|
||||||
Version: 0.3.0
|
|
||||||
Release: 3
|
|
||||||
License: GPLv3
|
|
||||||
Group: Networking/File transfer
|
|
||||||
Source: uhub-%{version}.tar.gz
|
|
||||||
URL: http://www.uhub.org
|
|
||||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
|
|
||||||
|
|
||||||
|
|
||||||
%description
|
|
||||||
uhub is a high performance peer-to-peer hub for the ADC network.
|
|
||||||
Its low memory footprint allows it to handle several thousand users on
|
|
||||||
high-end servers, or a small private hub on embedded hardware.
|
|
||||||
|
|
||||||
Key features:
|
|
||||||
- High performance and low memory usage
|
|
||||||
- IPv4 and IPv6 support
|
|
||||||
- Experimental SSL support (optional)
|
|
||||||
- Advanced access control support
|
|
||||||
- Easy configuration
|
|
||||||
|
|
||||||
|
|
||||||
%prep
|
|
||||||
%setup -q -n %{name}-%{version}
|
|
||||||
|
|
||||||
%build
|
|
||||||
echo RPM_BUILD_ROOT = $RPM_BUILD_ROOT
|
|
||||||
make
|
|
||||||
|
|
||||||
%install
|
|
||||||
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
|
||||||
mkdir -p $RPM_BUILD_ROOT/etc/uhub
|
|
||||||
mkdir -p $RPM_BUILD_ROOT/etc/init.d
|
|
||||||
mkdir -p $RPM_BUILD_ROOT/etc/logrotate.d
|
|
||||||
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
|
|
||||||
mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1
|
|
||||||
|
|
||||||
install uhub $RPM_BUILD_ROOT/usr/bin/
|
|
||||||
> doc/motd.txt
|
|
||||||
install -m644 doc/uhub.conf doc/users.conf doc/rules.txt doc/motd.txt $RPM_BUILD_ROOT/etc/uhub
|
|
||||||
install doc/init.d.RedHat/etc/init.d/uhub $RPM_BUILD_ROOT/etc/init.d
|
|
||||||
install -m644 doc/init.d.RedHat/etc/sysconfig/uhub $RPM_BUILD_ROOT/etc/sysconfig/
|
|
||||||
install -m644 doc/init.d.RedHat/etc/logrotate.d/uhub $RPM_BUILD_ROOT/etc/logrotate.d/
|
|
||||||
/bin/gzip -9c doc/uhub.1 > doc/uhub.1.gz &&
|
|
||||||
install -m644 doc/uhub.1.gz $RPM_BUILD_ROOT/usr/share/man/man1
|
|
||||||
|
|
||||||
|
|
||||||
%files
|
|
||||||
%defattr(-,root,root)
|
|
||||||
%doc AUTHORS BUGS COPYING ChangeLog README TODO doc/Doxyfile doc/architecture.txt doc/compile.txt doc/extensions.txt doc/getstarted.txt doc/uhub.dot
|
|
||||||
%config(noreplace) /etc/uhub/uhub.conf
|
|
||||||
#%{_sysconfdir}/uhub/uhub.conf
|
|
||||||
%config(noreplace) %{_sysconfdir}/uhub/users.conf
|
|
||||||
%config(noreplace) %{_sysconfdir}/uhub/motd.txt
|
|
||||||
%config(noreplace) %{_sysconfdir}/uhub/rules.txt
|
|
||||||
%{_sysconfdir}/init.d/uhub
|
|
||||||
%config(noreplace) %{_sysconfdir}/logrotate.d/uhub
|
|
||||||
%config(noreplace) %{_sysconfdir}/sysconfig/uhub
|
|
||||||
/usr/share/man/man1/uhub.1.gz
|
|
||||||
%{_bindir}/uhub
|
|
||||||
|
|
||||||
|
|
||||||
%clean
|
|
||||||
rm -rf $RPM_BUILD_ROOT
|
|
||||||
|
|
||||||
%post
|
|
||||||
/sbin/chkconfig --add uhub
|
|
||||||
if [ $1 -gt 1 ] ; then
|
|
||||||
/etc/rc.d/init.d/uhub restart >/dev/null || :
|
|
||||||
fi
|
|
||||||
# need more informations about add services and users in system
|
|
||||||
/usr/sbin/adduser -M -d /tmp -G nobody -s /sbin/nologin -c 'The Uhub ADC p2p hub Daemon' uhub >/dev/null 2>&1 ||:
|
|
||||||
|
|
||||||
%changelog
|
|
||||||
* Tue Jan 31 2010 E_zombie
|
|
||||||
- change GROUP
|
|
||||||
- chmod for files
|
|
||||||
- add postinstall scripts
|
|
||||||
- fix "License"
|
|
||||||
* Tue Jan 26 2010 E_zombie
|
|
||||||
- first .spec release
|
|
||||||
|
|
||||||
|
|
||||||
@@ -12,8 +12,8 @@
|
|||||||
# 'ban_cid' - banned user by cid
|
# 'ban_cid' - banned user by cid
|
||||||
|
|
||||||
# Administrator
|
# Administrator
|
||||||
# user_admin userA:password1
|
user_admin Dj_Offset:uhub
|
||||||
# user_op userB:password2
|
user_op janvidar:password
|
||||||
|
|
||||||
# We don't want users with these names
|
# We don't want users with these names
|
||||||
deny_nick Hub-Security
|
deny_nick Hub-Security
|
||||||
|
|||||||
154
src/adc/sid.c
154
src/adc/sid.c
@@ -1,154 +0,0 @@
|
|||||||
/*
|
|
||||||
* uhub - A tiny ADC p2p connection hub
|
|
||||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "uhub.h"
|
|
||||||
|
|
||||||
const char* BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
|
||||||
|
|
||||||
char* sid_to_string(sid_t sid_)
|
|
||||||
{
|
|
||||||
static char t_sid[5];
|
|
||||||
sid_t sid = (sid_ & 0xFFFFF); /* 20 bits only */
|
|
||||||
sid_t A, B, C, D = 0;
|
|
||||||
D = (sid % 32);
|
|
||||||
sid = (sid - D) / 32;
|
|
||||||
C = (sid % 32);
|
|
||||||
sid = (sid - C) / 32;
|
|
||||||
B = (sid % 32);
|
|
||||||
sid = (sid - B) / 32;
|
|
||||||
A = (sid % 32);
|
|
||||||
t_sid[0] = BASE32_ALPHABET[A];
|
|
||||||
t_sid[1] = BASE32_ALPHABET[B];
|
|
||||||
t_sid[2] = BASE32_ALPHABET[C];
|
|
||||||
t_sid[3] = BASE32_ALPHABET[D];
|
|
||||||
t_sid[4] = 0;
|
|
||||||
return t_sid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
sid_t string_to_sid(const char* sid)
|
|
||||||
{
|
|
||||||
sid_t nsid = 0;
|
|
||||||
sid_t n, x;
|
|
||||||
sid_t factors[] = { 32768, 1024, 32, 1};
|
|
||||||
|
|
||||||
if (!sid || strlen(sid) != 4) return 0;
|
|
||||||
|
|
||||||
for (n = 0; n < 4; n++) {
|
|
||||||
for (x = 0; x < strlen(BASE32_ALPHABET); x++)
|
|
||||||
if (sid[n] == BASE32_ALPHABET[x]) break;
|
|
||||||
if (x == 32) return 0;
|
|
||||||
nsid += x * factors[n];
|
|
||||||
}
|
|
||||||
return nsid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Session IDs are heavily reused, since they are a fairly scarce
|
|
||||||
* resource. Only one (2^10)-1 exist, since it is a four byte base32-encoded
|
|
||||||
* value and 'AAAA' (0) is reserved for the hub.
|
|
||||||
*
|
|
||||||
* Initialize with sid_initialize(), which sets min and max to one, and count to 0.
|
|
||||||
*
|
|
||||||
* When allocating a session ID:
|
|
||||||
* - If 'count' is less than the pool size (max-min), then allocate within the pool
|
|
||||||
* - Increase the pool size (see below)
|
|
||||||
* - If unable to do that, hub is really full - don't let anyone in!
|
|
||||||
*
|
|
||||||
* When freeing a session ID:
|
|
||||||
* - If the session ID being freed is 'max', then decrease the pool size by one.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct sid_pool
|
|
||||||
{
|
|
||||||
sid_t min;
|
|
||||||
sid_t max;
|
|
||||||
sid_t count;
|
|
||||||
struct hub_user** map;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct sid_pool* sid_pool_create(sid_t max)
|
|
||||||
{
|
|
||||||
struct sid_pool* pool = hub_malloc(sizeof(struct sid_pool));
|
|
||||||
if (!pool)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
pool->min = 1;
|
|
||||||
pool->max = max + 1;
|
|
||||||
pool->count = 0;
|
|
||||||
pool->map = hub_malloc_zero(sizeof(struct hub_user*) * pool->max);
|
|
||||||
if (!pool->map)
|
|
||||||
{
|
|
||||||
hub_free(pool);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
pool->map[0] = (struct hub_user*) pool; /* hack to reserve the first sid. */
|
|
||||||
|
|
||||||
#ifdef DEBUG_SID
|
|
||||||
LOG_DUMP("SID_POOL: max=%d", (int) pool->max);
|
|
||||||
#endif
|
|
||||||
return pool;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sid_pool_destroy(struct sid_pool* pool)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG_SID
|
|
||||||
LOG_DUMP("SID_POOL: destroying, current allocs=%d", (int) pool->count);
|
|
||||||
#endif
|
|
||||||
hub_free(pool->map);
|
|
||||||
hub_free(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++) ;
|
|
||||||
|
|
||||||
#ifdef DEBUG_SID
|
|
||||||
LOG_DUMP("SID_ALLOC: %d, user=%p", (int) n, user);
|
|
||||||
#endif
|
|
||||||
pool->map[n] = user;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sid_free(struct sid_pool* pool, sid_t sid)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG_SID
|
|
||||||
LOG_DUMP("SID_FREE: %d", (int) sid);
|
|
||||||
#endif
|
|
||||||
pool->map[sid] = 0;
|
|
||||||
pool->count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct hub_user* sid_lookup(struct sid_pool* pool, sid_t sid)
|
|
||||||
{
|
|
||||||
if (!sid || (sid >= pool->max))
|
|
||||||
return 0;
|
|
||||||
return pool->map[sid];
|
|
||||||
}
|
|
||||||
951
src/adcrush.c
Normal file
951
src/adcrush.c
Normal file
@@ -0,0 +1,951 @@
|
|||||||
|
/**
|
||||||
|
* An ADC client emulator.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
#define ADC_CLIENTS_DEFAULT 100
|
||||||
|
#define ADC_MAX_CLIENTS 25000
|
||||||
|
|
||||||
|
#define ADC_BUFSIZE 16384
|
||||||
|
#define ADC_SIDSIZE 4
|
||||||
|
#define ADC_CID_SIZE 39
|
||||||
|
|
||||||
|
#define BIG_BUFSIZE 131072
|
||||||
|
#define TIGERSIZE 24
|
||||||
|
|
||||||
|
#define ADC_HANDSHAKE "HSUP ADBASE ADTIGR\n"
|
||||||
|
#define ADCRUSH "adcrush/0.2"
|
||||||
|
#define ADC_NICK "[BOT]adcrush"
|
||||||
|
#define ADC_DESC "crash\\stest\\sdummy"
|
||||||
|
|
||||||
|
struct ADC_client;
|
||||||
|
|
||||||
|
static void ADC_client_on_disconnected(struct ADC_client*);
|
||||||
|
static void ADC_client_on_connected(struct ADC_client*);
|
||||||
|
static void ADC_client_on_login(struct ADC_client*);
|
||||||
|
static void ADC_client_connect(struct ADC_client*);
|
||||||
|
static void ADC_client_disconnect(struct ADC_client*);
|
||||||
|
static int ADC_client_create(struct ADC_client* client, int num);
|
||||||
|
static void ADC_client_destroy(struct ADC_client* client);
|
||||||
|
|
||||||
|
static int cfg_mode = 0; // See enum operationMode
|
||||||
|
static char* cfg_host = 0;
|
||||||
|
static int cfg_port = 0;
|
||||||
|
static int cfg_debug = 0; /* debug level */
|
||||||
|
static int cfg_level = 1; /* activity level (0..3) */
|
||||||
|
static int cfg_chat = 0; /* chat mode, allow sending chat messages */
|
||||||
|
static int cfg_quiet = 0; /* quiet mode (no output) */
|
||||||
|
static int cfg_clients = ADC_CLIENTS_DEFAULT; /* number of clients */
|
||||||
|
|
||||||
|
static int running = 1;
|
||||||
|
|
||||||
|
static struct sockaddr_in saddr;
|
||||||
|
|
||||||
|
enum commandMode
|
||||||
|
{
|
||||||
|
cm_bcast = 0x01, /* B - broadcast */
|
||||||
|
cm_dir = 0x02, /* D - direct message */
|
||||||
|
cm_echo = 0x04, /* E - echo message */
|
||||||
|
cm_fcast = 0x08, /* F - feature cast message */
|
||||||
|
cm_c2h = 0x10, /* H - client to hub message */
|
||||||
|
cm_h2c = 0x20, /* I - hub to client message */
|
||||||
|
cm_c2c = 0x40, /* C - client to client message */
|
||||||
|
cm_udp = 0x80, /* U - udp message (client to client) */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum commandValidity
|
||||||
|
{
|
||||||
|
cv_protocol = 0x01,
|
||||||
|
cv_identify = 0x02,
|
||||||
|
cv_verify = 0x04,
|
||||||
|
cv_normal = 0x08,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum protocolState
|
||||||
|
{
|
||||||
|
ps_none = 0x00, /* none or disconnected */
|
||||||
|
ps_conn = 0x01, /* connecting... */
|
||||||
|
ps_protocol = 0x02,
|
||||||
|
ps_identify = 0x04,
|
||||||
|
ps_verify = 0x08,
|
||||||
|
ps_normal = 0x10,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum operationMode
|
||||||
|
{
|
||||||
|
mode_performance = 0x01,
|
||||||
|
mode_bugs = 0x02,
|
||||||
|
mode_security = 0x04,
|
||||||
|
mode_log = 0x08,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct commandPattern
|
||||||
|
{
|
||||||
|
unsigned char mode; /* see enum commandMode */
|
||||||
|
char cmd[3];
|
||||||
|
unsigned char validity; /* see enum commandValidity */
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct commandPattern patterns[] =
|
||||||
|
{
|
||||||
|
{ cm_c2h | cm_c2c | cm_h2c, "SUP", cv_protocol | cv_normal }, /* protocol support */
|
||||||
|
{ cm_bcast | cm_h2c | cm_c2c, "INF", cv_identify | cv_verify | cv_normal }, /* info message */
|
||||||
|
{ cm_bcast | cm_h2c | cm_c2c | cm_c2h | cm_udp, "STA", cv_protocol | cv_identify | cv_verify | cv_normal }, /* status message */
|
||||||
|
{ cm_bcast | cm_dir | cm_echo | cm_h2c, "MSG", cv_normal }, /* chat message */
|
||||||
|
{ cm_bcast | cm_dir | cm_echo | cm_fcast, "SCH", cv_normal }, /* search */
|
||||||
|
{ cm_dir | cm_udp, "RES", cv_normal }, /* search result */
|
||||||
|
{ cm_dir | cm_echo, "CTM", cv_normal }, /* connect to me */
|
||||||
|
{ cm_dir | cm_echo, "RCM", cv_normal }, /* reversed, connect to me */
|
||||||
|
{ cm_h2c, "QUI", cv_normal }, /* quit message */
|
||||||
|
{ cm_h2c, "GPA", cv_identify }, /* password request */
|
||||||
|
{ cm_c2h, "PAS", cv_verify } /* password response */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_CHAT_MSGS 35
|
||||||
|
const char* chat_messages[MAX_CHAT_MSGS] = {
|
||||||
|
"hello",
|
||||||
|
"I'm an annoying robot, configured to chat in order to measure performance of the hub.",
|
||||||
|
"I apologize for the inconvenience.",
|
||||||
|
".",
|
||||||
|
":)",
|
||||||
|
"can anyone help me, pls?",
|
||||||
|
"wtf?",
|
||||||
|
"bullshit",
|
||||||
|
"resistance is futile.",
|
||||||
|
"You crossed the line first, sir. You squeezed them, you hammered them to the point of desperation. And in their desperation they turned to a man they didn't fully understand.",
|
||||||
|
"beam me up, scotty",
|
||||||
|
"morning",
|
||||||
|
"You know where Harvey is? You know who he is?",
|
||||||
|
"gtg",
|
||||||
|
"thanks",
|
||||||
|
"*punt*",
|
||||||
|
"*nudge*",
|
||||||
|
"that's ok",
|
||||||
|
"...anyway",
|
||||||
|
"hola",
|
||||||
|
"hey",
|
||||||
|
"hi",
|
||||||
|
"nevermind",
|
||||||
|
"i think so",
|
||||||
|
"dunno",
|
||||||
|
"debian ftw",
|
||||||
|
"oops",
|
||||||
|
"how do I search?",
|
||||||
|
"how do I enable active mode?",
|
||||||
|
"home, sweet home...",
|
||||||
|
"later",
|
||||||
|
"Good evening, ladies and gentlemen. We are tonight's entertainment! I only have one question. Where is Harvey Dent?",
|
||||||
|
"You know where I can find Harvey? I need to talk to him about something. Just something, a little.",
|
||||||
|
"We really should stop fighting, we'll miss the fireworks!",
|
||||||
|
"Wanna know how I got these scars?",
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_SEARCH_MSGS 10
|
||||||
|
const char* search_messages[MAX_SEARCH_MSGS] = {
|
||||||
|
"ANmp3 TOauto",
|
||||||
|
"ANxxx TOauto",
|
||||||
|
"ANdivx TOauto",
|
||||||
|
"ANtest ANfoo TOauto",
|
||||||
|
"ANwmv TO1289718",
|
||||||
|
"ANbabe TO8981884",
|
||||||
|
"ANpr0n TOauto",
|
||||||
|
"ANmusic TOauto",
|
||||||
|
"ANvideo TOauto",
|
||||||
|
"ANburnout ANps3 TOauto",
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ADC_client
|
||||||
|
{
|
||||||
|
int sd;
|
||||||
|
int num;
|
||||||
|
sid_t sid;
|
||||||
|
enum protocolState state;
|
||||||
|
char info[ADC_BUFSIZE];
|
||||||
|
char recvbuf[BIG_BUFSIZE];
|
||||||
|
char sendbuf[BIG_BUFSIZE];
|
||||||
|
size_t s_offset;
|
||||||
|
size_t r_offset;
|
||||||
|
struct event ev_read;
|
||||||
|
struct event ev_write;
|
||||||
|
struct event ev_timer;
|
||||||
|
size_t timeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void bot_output(struct ADC_client* client, const char* format, ...)
|
||||||
|
{
|
||||||
|
char logmsg[1024];
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
vsnprintf(logmsg, 1024, format, args);
|
||||||
|
va_end(args);
|
||||||
|
if (cfg_mode == mode_log)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "%s\n", logmsg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cfg_debug)
|
||||||
|
fprintf(stdout, "* [%4d] %s\n", client->num, logmsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void adc_cid_pid(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
char seed[64];
|
||||||
|
char pid[64];
|
||||||
|
char cid[64];
|
||||||
|
uint64_t tiger_res1[3];
|
||||||
|
uint64_t tiger_res2[3];
|
||||||
|
|
||||||
|
/* create cid+pid pair */
|
||||||
|
memset(seed, 0, 64);
|
||||||
|
snprintf(seed, 64, ADCRUSH "%p/%d", client, (int) client->num);
|
||||||
|
|
||||||
|
tiger((uint64_t*) seed, strlen(seed), tiger_res1);
|
||||||
|
base32_encode((unsigned char*) tiger_res1, TIGERSIZE, pid);
|
||||||
|
tiger((uint64_t*) tiger_res1, TIGERSIZE, tiger_res2);
|
||||||
|
base32_encode((unsigned char*) tiger_res2, TIGERSIZE, cid);
|
||||||
|
|
||||||
|
cid[ADC_CID_SIZE] = 0;
|
||||||
|
pid[ADC_CID_SIZE] = 0;
|
||||||
|
|
||||||
|
strcat(client->info, " PD");
|
||||||
|
strcat(client->info, pid);
|
||||||
|
strcat(client->info, " ID");
|
||||||
|
strcat(client->info, cid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t get_wait_rand(size_t max)
|
||||||
|
{
|
||||||
|
static size_t next = 0;
|
||||||
|
if (next == 0) next = (size_t) time(0);
|
||||||
|
next = (next * 1103515245) + 12345;
|
||||||
|
return ((size_t )(next / 65536) % max);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void client_reschedule_timeout(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
size_t next_timeout = 0;
|
||||||
|
struct timeval timeout = { 0, 0 };
|
||||||
|
|
||||||
|
switch (client->state)
|
||||||
|
{
|
||||||
|
case ps_conn: next_timeout = 30; break;
|
||||||
|
case ps_protocol: next_timeout = 30; break;
|
||||||
|
case ps_identify: next_timeout = 30; break;
|
||||||
|
case ps_verify: next_timeout = 30; break;
|
||||||
|
case ps_normal: next_timeout = 120; break;
|
||||||
|
case ps_none: next_timeout = 120; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client->state == ps_normal || client->state == ps_none)
|
||||||
|
{
|
||||||
|
switch (cfg_level)
|
||||||
|
{
|
||||||
|
case 0: /* polite */
|
||||||
|
next_timeout *= 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: /* normal */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: /* aggressive */
|
||||||
|
next_timeout /= 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: /* excessive */
|
||||||
|
next_timeout /= 16;
|
||||||
|
|
||||||
|
case 4: /* excessive */
|
||||||
|
next_timeout /= 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (client->state == ps_conn)
|
||||||
|
client->timeout = MAX(next_timeout, 1);
|
||||||
|
else
|
||||||
|
client->timeout = get_wait_rand(MAX(next_timeout, 1));
|
||||||
|
|
||||||
|
if (!client->timeout) client->timeout++;
|
||||||
|
|
||||||
|
timeout.tv_sec = (time_t) client->timeout;
|
||||||
|
evtimer_add(&client->ev_timer, &timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_state_timeout(struct ADC_client* client, enum protocolState state)
|
||||||
|
{
|
||||||
|
client->state = state;
|
||||||
|
client_reschedule_timeout(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_client(struct ADC_client* client, char* msg)
|
||||||
|
{
|
||||||
|
int ret = net_send(client->sd, msg, strlen(msg), UHUB_SEND_SIGNAL);
|
||||||
|
|
||||||
|
if (cfg_debug > 1)
|
||||||
|
{
|
||||||
|
char* dump = strdup(msg);
|
||||||
|
dump[strlen(msg) - 1] = 0;
|
||||||
|
bot_output(client, "- SEND: '%s'", dump);
|
||||||
|
free(dump);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != strlen(msg))
|
||||||
|
{
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
if (net_error() != EWOULDBLOCK)
|
||||||
|
ADC_client_on_disconnected(client);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* FIXME: Not all data sent! */
|
||||||
|
printf("ret (%d) != msg->length (%d)\n", ret, (int) strlen(msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ADC_client_on_connected(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
send_client(client, ADC_HANDSHAKE);
|
||||||
|
set_state_timeout(client, ps_protocol);
|
||||||
|
bot_output(client, "connected.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ADC_client_on_disconnected(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
event_del(&client->ev_read);
|
||||||
|
event_del(&client->ev_write);
|
||||||
|
|
||||||
|
net_close(client->sd);
|
||||||
|
client->sd = -1;
|
||||||
|
|
||||||
|
bot_output(client, "disconnected.");
|
||||||
|
set_state_timeout(client, ps_none);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ADC_client_on_login(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
bot_output(client, "logged in.");
|
||||||
|
set_state_timeout(client, ps_normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void send_client_info(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
client->info[0] = 0;
|
||||||
|
strcat(client->info, "BINF ");
|
||||||
|
strcat(client->info, sid_to_string(client->sid));
|
||||||
|
strcat(client->info, " NI" ADC_NICK);
|
||||||
|
if (cfg_clients > 1)
|
||||||
|
{
|
||||||
|
strcat(client->info, "_");
|
||||||
|
strcat(client->info, uhub_itoa(client->num));
|
||||||
|
}
|
||||||
|
strcat(client->info, " VE" ADCRUSH);
|
||||||
|
strcat(client->info, " DE" ADC_DESC);
|
||||||
|
strcat(client->info, " I40.0.0.0");
|
||||||
|
strcat(client->info, " EMuhub@extatic.org");
|
||||||
|
strcat(client->info, " SL3");
|
||||||
|
strcat(client->info, " HN1");
|
||||||
|
strcat(client->info, " HR1");
|
||||||
|
strcat(client->info, " HO1");
|
||||||
|
|
||||||
|
adc_cid_pid(client);
|
||||||
|
|
||||||
|
strcat(client->info, "\n");
|
||||||
|
|
||||||
|
send_client(client, client->info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token);
|
||||||
|
|
||||||
|
static int recv_client(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
ssize_t size = 0;
|
||||||
|
if (cfg_mode != mode_performance || (cfg_mode == mode_performance && (get_wait_rand(100) < (90 - (15 * cfg_level)))))
|
||||||
|
{
|
||||||
|
size = net_recv(client->sd, &client->recvbuf[client->r_offset], ADC_BUFSIZE - client->r_offset, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (get_wait_rand(1000) == 99)
|
||||||
|
return -1; /* Can break tings badly! :-) */
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (size == 0 || ((size == -1 && net_error() != EWOULDBLOCK)))
|
||||||
|
return -1;
|
||||||
|
client->recvbuf[client->r_offset + size] = 0;
|
||||||
|
|
||||||
|
char* start = client->recvbuf;
|
||||||
|
char* pos;
|
||||||
|
char* lastPos;
|
||||||
|
while ((pos = strchr(start, '\n')))
|
||||||
|
{
|
||||||
|
lastPos = pos;
|
||||||
|
pos[0] = 0;
|
||||||
|
|
||||||
|
if (cfg_debug > 1)
|
||||||
|
{
|
||||||
|
bot_output(client, "- RECV: '%s'", start);
|
||||||
|
}
|
||||||
|
|
||||||
|
fourcc_t cmd = 0;
|
||||||
|
if (strlen(start) < 4)
|
||||||
|
{
|
||||||
|
bot_output(client, "Unexpected response from hub: '%s'", start);
|
||||||
|
start = &pos[1];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = FOURCC(start[0], start[1], start[2], start[3]);
|
||||||
|
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case ADC_CMD_ISUP:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CMD_ISID:
|
||||||
|
if (client->state == ps_protocol)
|
||||||
|
{
|
||||||
|
client->sid = string_to_sid(&start[5]);
|
||||||
|
client->state = ps_identify;
|
||||||
|
send_client_info(client);
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CMD_IINF:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CMD_BSCH:
|
||||||
|
case ADC_CMD_FSCH:
|
||||||
|
{
|
||||||
|
if (get_wait_rand(100) > (90 - (10 * cfg_level)) && cfg_mode == mode_performance)
|
||||||
|
{
|
||||||
|
sid_t target = string_to_sid(&start[5]);
|
||||||
|
const char* what = strstr(&start[5], " AN");
|
||||||
|
const char* token = strstr(&start[5], " TO");
|
||||||
|
char* split = 0;
|
||||||
|
if (!token || !what) break;
|
||||||
|
|
||||||
|
token += 3;
|
||||||
|
what += 3;
|
||||||
|
|
||||||
|
split = strchr(what, ' ');
|
||||||
|
if (!split) break;
|
||||||
|
else split[0] = '0';
|
||||||
|
|
||||||
|
split = strchr(token, ' ');
|
||||||
|
if (split) split[0] = '0';
|
||||||
|
|
||||||
|
perf_result(client, target, what, token);
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ADC_CMD_BINF:
|
||||||
|
{
|
||||||
|
if (strlen(start) > 9)
|
||||||
|
{
|
||||||
|
char t = start[9]; start[9] = 0; sid_t sid = string_to_sid(&start[5]); start[9] = t;
|
||||||
|
|
||||||
|
if (sid == client->sid)
|
||||||
|
{
|
||||||
|
if (client->state == ps_verify || client->state == ps_identify)
|
||||||
|
{
|
||||||
|
ADC_client_on_login(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ADC_CMD_ISTA:
|
||||||
|
if (strncmp(start, "ISTA 000", 8))
|
||||||
|
{
|
||||||
|
bot_output(client, "status: '%s'\n", (start + 9));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = &pos[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
client->r_offset = strlen(lastPos);
|
||||||
|
memmove(client->recvbuf, lastPos, strlen(lastPos));
|
||||||
|
memset(&client->recvbuf[client->r_offset], 0, ADC_BUFSIZE-client->r_offset);
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADC_client_connect(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
struct timeval timeout = { TIMEOUT_IDLE, 0 };
|
||||||
|
net_connect(client->sd, (struct sockaddr*) &saddr, sizeof(struct sockaddr_in));
|
||||||
|
set_state_timeout(client, ps_conn);
|
||||||
|
event_add(&client->ev_read, &timeout);
|
||||||
|
event_add(&client->ev_write, &timeout);
|
||||||
|
bot_output(client, "connecting...");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADC_client_wait_connect(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
set_state_timeout(client, ps_none);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ADC_client_disconnect(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
if (client->sd != -1)
|
||||||
|
{
|
||||||
|
net_close(client->sd);
|
||||||
|
client->sd = -1;
|
||||||
|
event_del(&client->ev_read);
|
||||||
|
event_del(&client->ev_write);
|
||||||
|
bot_output(client, "disconnected.");
|
||||||
|
|
||||||
|
if (running)
|
||||||
|
{
|
||||||
|
ADC_client_destroy(client);
|
||||||
|
ADC_client_create(client, client->num);
|
||||||
|
ADC_client_connect(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void perf_chat(struct ADC_client* client, int priv)
|
||||||
|
{
|
||||||
|
char buf[1024] = { 0, };
|
||||||
|
size_t r = get_wait_rand(MAX_CHAT_MSGS-1);
|
||||||
|
char* msg = adc_msg_escape(chat_messages[r]);
|
||||||
|
|
||||||
|
if (priv)
|
||||||
|
{
|
||||||
|
strcat(buf, "EMSG ");
|
||||||
|
strcat(buf, sid_to_string(client->sid));
|
||||||
|
strcat(buf, " ");
|
||||||
|
strcat(buf, sid_to_string(client->sid));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcat(buf, "BMSG ");
|
||||||
|
strcat(buf, sid_to_string(client->sid));
|
||||||
|
}
|
||||||
|
strcat(buf, " ");
|
||||||
|
|
||||||
|
strcat(buf, msg);
|
||||||
|
hub_free(msg);
|
||||||
|
|
||||||
|
strcat(buf, "\n");
|
||||||
|
send_client(client, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void perf_search(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
char buf[1024] = { 0, };
|
||||||
|
size_t r = get_wait_rand(MAX_SEARCH_MSGS-1);
|
||||||
|
size_t pst = get_wait_rand(100);
|
||||||
|
|
||||||
|
if (pst > 80)
|
||||||
|
{
|
||||||
|
strcat(buf, "FSCH ");
|
||||||
|
strcat(buf, sid_to_string(client->sid));
|
||||||
|
strcat(buf, " +TCP4 ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcat(buf, "BSCH ");
|
||||||
|
strcat(buf, sid_to_string(client->sid));
|
||||||
|
strcat(buf, " ");
|
||||||
|
}
|
||||||
|
strcat(buf, search_messages[r]);
|
||||||
|
strcat(buf, "\n");
|
||||||
|
send_client(client, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token)
|
||||||
|
{
|
||||||
|
char buf[1024] = { 0, };
|
||||||
|
strcat(buf, "DRES ");
|
||||||
|
strcat(buf, sid_to_string(client->sid));
|
||||||
|
strcat(buf, " ");
|
||||||
|
strcat(buf, sid_to_string(target));
|
||||||
|
strcat(buf, " FN" "test/");
|
||||||
|
strcat(buf, what);
|
||||||
|
strcat(buf, ".dat");
|
||||||
|
strcat(buf, " SL" "0");
|
||||||
|
strcat(buf, " SI" "908987128912");
|
||||||
|
strcat(buf, " TR" "5T6YJYKO3WECS52BKWVSOP5VUG4IKNSZBZ5YHBA");
|
||||||
|
strcat(buf, " TO");
|
||||||
|
strcat(buf, token);
|
||||||
|
strcat(buf, "\n");
|
||||||
|
send_client(client, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void perf_ctm(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
char buf[1024] = { 0, };
|
||||||
|
strcat(buf, "DCTM ");
|
||||||
|
strcat(buf, sid_to_string(client->sid));
|
||||||
|
strcat(buf, " ");
|
||||||
|
strcat(buf, sid_to_string(client->sid));
|
||||||
|
strcat(buf, " ");
|
||||||
|
strcat(buf, "ADC/1.0");
|
||||||
|
strcat(buf, " TOKEN111");
|
||||||
|
strcat(buf, sid_to_string(client->sid));
|
||||||
|
strcat(buf, "\n");
|
||||||
|
send_client(client, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void perf_update(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
char buf[1024] = { 0, };
|
||||||
|
int n = (int) get_wait_rand(10)+1;
|
||||||
|
|
||||||
|
strcat(buf, "BINF ");
|
||||||
|
strcat(buf, sid_to_string(client->sid));
|
||||||
|
strcat(buf, " HN");
|
||||||
|
strcat(buf, uhub_itoa(n));
|
||||||
|
|
||||||
|
strcat(buf, "\n");
|
||||||
|
send_client(client, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void perf_normal_action(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
size_t r = get_wait_rand(5);
|
||||||
|
size_t p = get_wait_rand(100);
|
||||||
|
|
||||||
|
switch (r)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if (p > (90 - (10 * cfg_level)))
|
||||||
|
{
|
||||||
|
if (cfg_debug > 1) bot_output(client, "timeout -> disconnect");
|
||||||
|
ADC_client_disconnect(client);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
if (cfg_chat)
|
||||||
|
{
|
||||||
|
if (cfg_debug > 1) bot_output(client, "timeout -> chat");
|
||||||
|
perf_chat(client, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
if (cfg_debug > 1) bot_output(client, "timeout -> search");
|
||||||
|
perf_search(client);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
if (cfg_debug > 1) bot_output(client, "timeout -> update");
|
||||||
|
perf_update(client);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
if (cfg_debug > 1) bot_output(client, "timeout -> privmsg");
|
||||||
|
perf_chat(client, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
if (cfg_debug > 1) bot_output(client, "timeout -> ctm/rcm");
|
||||||
|
perf_ctm(client);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
client_reschedule_timeout(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
void event_callback(int fd, short ev, void *arg)
|
||||||
|
{
|
||||||
|
struct ADC_client* client = (struct ADC_client*) arg;
|
||||||
|
|
||||||
|
if (ev & EV_READ)
|
||||||
|
{
|
||||||
|
if (recv_client(client) == -1)
|
||||||
|
{
|
||||||
|
ADC_client_on_disconnected(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev & EV_TIMEOUT)
|
||||||
|
{
|
||||||
|
if (client->state == ps_none)
|
||||||
|
{
|
||||||
|
if (client->sd == -1)
|
||||||
|
{
|
||||||
|
ADC_client_create(client, client->num);
|
||||||
|
}
|
||||||
|
|
||||||
|
ADC_client_connect(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
if (client->state == ps_normal && cfg_mode == mode_performance)
|
||||||
|
{
|
||||||
|
perf_normal_action(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev & EV_WRITE)
|
||||||
|
{
|
||||||
|
if (client->state == ps_conn)
|
||||||
|
{
|
||||||
|
ADC_client_on_connected(client);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* FIXME: Call send again */
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ADC_client_create(struct ADC_client* client, int num)
|
||||||
|
{
|
||||||
|
struct timeval timeout = { 0, 0 };
|
||||||
|
|
||||||
|
memset(client, 0, sizeof(struct ADC_client));
|
||||||
|
client->num = num;
|
||||||
|
|
||||||
|
client->sd = net_socket_create(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (client->sd == -1) return -1;
|
||||||
|
|
||||||
|
event_set(&client->ev_write, client->sd, EV_WRITE, event_callback, client);
|
||||||
|
event_set(&client->ev_read, client->sd, EV_READ | EV_PERSIST, event_callback, client);
|
||||||
|
|
||||||
|
net_set_nonblocking(client->sd, 1);
|
||||||
|
|
||||||
|
timeout.tv_sec = client->timeout;
|
||||||
|
evtimer_set(&client->ev_timer, event_callback, client);
|
||||||
|
|
||||||
|
set_state_timeout(client, ps_none);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADC_client_destroy(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
ADC_client_disconnect(client);
|
||||||
|
evtimer_del(&client->ev_timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void runloop(size_t clients)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
struct ADC_client* client[ADC_MAX_CLIENTS];
|
||||||
|
|
||||||
|
for (n = 0; n < clients; n++)
|
||||||
|
{
|
||||||
|
struct ADC_client* c = malloc(sizeof(struct ADC_client));
|
||||||
|
client[n] = c;
|
||||||
|
|
||||||
|
ADC_client_create(c, n);
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
ADC_client_connect(c);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ADC_client_wait_connect(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
event_dispatch();
|
||||||
|
|
||||||
|
for (n = 0; n < clients; n++)
|
||||||
|
{
|
||||||
|
ADC_client_destroy(client[n]);
|
||||||
|
free(client[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_version()
|
||||||
|
{
|
||||||
|
printf(ADCRUSH "\n");
|
||||||
|
printf("Copyright (C) 2008-2009, Jan Vidar Krey\n");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_usage(const char* program)
|
||||||
|
{
|
||||||
|
print_version();
|
||||||
|
|
||||||
|
printf("Usage: %s <mode> (adc://<host>:<port>) [options]\n", program);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
printf(" Modes\n");
|
||||||
|
printf(" perf Do performance testing using multiple clients\n");
|
||||||
|
printf(" bugs Bugs mode, use fuzzer to construct pseudo-random commands.\n");
|
||||||
|
printf(" security Perform security tests for the hub.\n");
|
||||||
|
printf(" log Connect one client to the hub and log the output hub.\n");
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
printf(" General options\n");
|
||||||
|
printf(" -c Allow broadcasting chat messages.\n");
|
||||||
|
printf(" -d Enable debug output.\n");
|
||||||
|
printf(" -q Quiet mode (no output).\n");
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
printf(" Performance options:\n");
|
||||||
|
printf(" -l <0-3> Level: 0=polite, 1=normal (default), 2=aggressive, 3=excessive.\n");
|
||||||
|
printf(" -n <num> Number of concurrent connections\n");
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int set_defaults()
|
||||||
|
{
|
||||||
|
switch (cfg_mode)
|
||||||
|
{
|
||||||
|
case mode_performance:
|
||||||
|
break;
|
||||||
|
case mode_bugs:
|
||||||
|
break;
|
||||||
|
case mode_security:
|
||||||
|
break;
|
||||||
|
case mode_log:
|
||||||
|
cfg_quiet = 0;
|
||||||
|
cfg_debug = 2;
|
||||||
|
cfg_clients = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_mode(const char* arg)
|
||||||
|
{
|
||||||
|
cfg_mode = 0;
|
||||||
|
|
||||||
|
if (!strcmp(arg, "perf"))
|
||||||
|
cfg_mode = mode_performance;
|
||||||
|
else if (!strcmp(arg, "bugs"))
|
||||||
|
cfg_mode = mode_bugs;
|
||||||
|
else if (!strcmp(arg, "security"))
|
||||||
|
cfg_mode = mode_security;
|
||||||
|
else if (!strcmp(arg, "log"))
|
||||||
|
cfg_mode = mode_log;
|
||||||
|
|
||||||
|
return cfg_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_address(const char* arg)
|
||||||
|
{
|
||||||
|
char* split;
|
||||||
|
struct hostent* dns;
|
||||||
|
struct in_addr* addr;
|
||||||
|
|
||||||
|
if (!arg)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (strlen(arg) < 9)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (strncmp(arg, "adc://", 6))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
split = strrchr(arg+6, ':');
|
||||||
|
if (split == 0 || strlen(split) < 2 || strlen(split) > 6)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cfg_port = strtol(split+1, NULL, 10);
|
||||||
|
if (cfg_port <= 0 || cfg_port > 65535)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
split[0] = 0;
|
||||||
|
|
||||||
|
dns = gethostbyname(arg+6);
|
||||||
|
if (dns)
|
||||||
|
{
|
||||||
|
addr = (struct in_addr*) dns->h_addr_list[0];
|
||||||
|
cfg_host = strdup(inet_ntoa(*addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cfg_host)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_arguments(int argc, char** argv)
|
||||||
|
{
|
||||||
|
int ok = 1;
|
||||||
|
int opt;
|
||||||
|
for (opt = 3; opt < argc; opt++)
|
||||||
|
{
|
||||||
|
if (!strcmp(argv[opt], "-c"))
|
||||||
|
cfg_chat = 1;
|
||||||
|
else if (!strncmp(argv[opt], "-d", 2))
|
||||||
|
cfg_debug += strlen(argv[opt]) - 1;
|
||||||
|
else if (!strcmp(argv[opt], "-q"))
|
||||||
|
cfg_quiet = 1;
|
||||||
|
else if (!strcmp(argv[opt], "-l") && (++opt) < argc)
|
||||||
|
{
|
||||||
|
cfg_level = MIN(MAX(uhub_atoi(argv[opt]), 0), 3);
|
||||||
|
}
|
||||||
|
else if (!strcmp(argv[opt], "-n") && (++opt) < argc)
|
||||||
|
{
|
||||||
|
cfg_clients = MIN(MAX(uhub_atoi(argv[opt]), 1), ADC_MAX_CLIENTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void parse_command_line(int argc, char** argv)
|
||||||
|
{
|
||||||
|
if (argc < 2 ||
|
||||||
|
!parse_mode(argv[1]) ||
|
||||||
|
!set_defaults() ||
|
||||||
|
!parse_address(argv[2]) ||
|
||||||
|
!parse_arguments(argc, argv))
|
||||||
|
{
|
||||||
|
print_usage(argv[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
parse_command_line(argc, argv);
|
||||||
|
|
||||||
|
net_initialize();
|
||||||
|
event_init();
|
||||||
|
|
||||||
|
memset(&saddr, 0, sizeof(saddr));
|
||||||
|
saddr.sin_family = AF_INET;
|
||||||
|
saddr.sin_port = htons(cfg_port);
|
||||||
|
net_string_to_address(AF_INET, cfg_host, &saddr.sin_addr);
|
||||||
|
|
||||||
|
runloop(cfg_clients);
|
||||||
|
net_shutdown();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -55,12 +55,12 @@ static int check_cmd_bool(const char* cmd, struct linked_list* list, char* line,
|
|||||||
data = strip_white_space(data);
|
data = strip_white_space(data);
|
||||||
if (!*data)
|
if (!*data)
|
||||||
{
|
{
|
||||||
LOG_FATAL("ACL parse error on line %d", line_count);
|
hub_log(log_fatal, "ACL parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_append(list, hub_strdup(data));
|
list_append(list, hub_strdup(data));
|
||||||
LOG_DEBUG("ACL: Deny access for: '%s' (%s)", data, cmd);
|
hub_log(log_debug, "ACL: Deny access for: '%s' (%s)", data, cmd);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -70,7 +70,7 @@ static int check_cmd_user(const char* cmd, int status, struct linked_list* list,
|
|||||||
{
|
{
|
||||||
char* data;
|
char* data;
|
||||||
char* data_extra;
|
char* data_extra;
|
||||||
struct hub_user_access_info* info = 0;
|
struct user_access_info* info = 0;
|
||||||
|
|
||||||
if (!strncmp(line, cmd, strlen(cmd)))
|
if (!strncmp(line, cmd, strlen(cmd)))
|
||||||
{
|
{
|
||||||
@@ -82,15 +82,15 @@ static int check_cmd_user(const char* cmd, int status, struct linked_list* list,
|
|||||||
data = strip_white_space(data);
|
data = strip_white_space(data);
|
||||||
if (!*data)
|
if (!*data)
|
||||||
{
|
{
|
||||||
LOG_FATAL("ACL parse error on line %d", line_count);
|
hub_log(log_fatal, "ACL parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
info = hub_malloc_zero(sizeof(struct hub_user_access_info));
|
info = hub_malloc_zero(sizeof(struct user_access_info));
|
||||||
|
|
||||||
if (!info)
|
if (!info)
|
||||||
{
|
{
|
||||||
LOG_ERROR("ACL parse error. Out of memory!");
|
hub_log(log_error, "ACL parse error. Out of memory!");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,14 +108,14 @@ static int check_cmd_user(const char* cmd, int status, struct linked_list* list,
|
|||||||
info->password = data_extra ? hub_strdup(data_extra) : 0;
|
info->password = data_extra ? hub_strdup(data_extra) : 0;
|
||||||
info->status = status;
|
info->status = status;
|
||||||
list_append(list, info);
|
list_append(list, info);
|
||||||
LOG_DEBUG("ACL: Added user '%s' (%s)", info->username, get_user_credential_string(info->status));
|
hub_log(log_debug, "ACL: Added user '%s' (%s)", info->username, get_user_credential_string(info->status));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void add_ip_range(struct linked_list* list, struct ip_range* info)
|
static void add_ip_range(struct linked_list* list, struct ip_ban_record* info)
|
||||||
{
|
{
|
||||||
char buf1[INET6_ADDRSTRLEN+1];
|
char buf1[INET6_ADDRSTRLEN+1];
|
||||||
char buf2[INET6_ADDRSTRLEN+1];
|
char buf2[INET6_ADDRSTRLEN+1];
|
||||||
@@ -130,44 +130,125 @@ static void add_ip_range(struct linked_list* list, struct ip_range* info)
|
|||||||
net_address_to_string(AF_INET6, &info->lo.internal_ip_data.in6, buf1, INET6_ADDRSTRLEN);
|
net_address_to_string(AF_INET6, &info->lo.internal_ip_data.in6, buf1, INET6_ADDRSTRLEN);
|
||||||
net_address_to_string(AF_INET6, &info->hi.internal_ip_data.in6, buf2, INET6_ADDRSTRLEN);
|
net_address_to_string(AF_INET6, &info->hi.internal_ip_data.in6, buf2, INET6_ADDRSTRLEN);
|
||||||
}
|
}
|
||||||
LOG_DEBUG("ACL: Added ip range: %s-%s", buf1, buf2);
|
hub_log(log_debug, "ACL: Deny access for: %s-%s", buf1, buf2);
|
||||||
|
|
||||||
list_append(list, info);
|
list_append(list, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int check_ip_range(const char* lo, const char* hi, struct ip_ban_record* info)
|
||||||
|
{
|
||||||
|
int ret1, ret2;
|
||||||
|
|
||||||
|
if ((ip_is_valid_ipv4(lo) && ip_is_valid_ipv4(hi)) ||
|
||||||
|
(ip_is_valid_ipv6(lo) && ip_is_valid_ipv6(hi)))
|
||||||
|
{
|
||||||
|
ret1 = ip_convert_to_binary(lo, &info->lo);
|
||||||
|
ret2 = ip_convert_to_binary(hi, &info->hi);
|
||||||
|
if (ret1 == -1 || ret2 == -1 || ret1 != ret2)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int check_ip_mask(const char* text_addr, int bits, struct ip_ban_record* info)
|
||||||
|
{
|
||||||
|
hub_log(log_debug, "ACL: Deny access for: %s/%d", text_addr, bits);
|
||||||
|
|
||||||
|
if (ip_is_valid_ipv4(text_addr) ||
|
||||||
|
ip_is_valid_ipv6(text_addr))
|
||||||
|
{
|
||||||
|
struct ip_addr_encap addr;
|
||||||
|
struct ip_addr_encap mask1;
|
||||||
|
struct ip_addr_encap mask2;
|
||||||
|
int af = ip_convert_to_binary(text_addr, &addr); /* 192.168.1.2 */
|
||||||
|
int maxbits = af == AF_INET6 ? 128 : 32;
|
||||||
|
ip_mask_create_left(af, bits, &mask1); /* 255.255.255.0 */
|
||||||
|
ip_mask_create_right(af, maxbits - bits, &mask2); /* 0.0.0.255 */
|
||||||
|
ip_mask_apply_AND(&addr, &mask1, &info->lo); /* 192.168.1.0 */
|
||||||
|
ip_mask_apply_OR(&info->lo, &mask2, &info->hi); /* 192.168.1.255 */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int check_cmd_addr(const char* cmd, struct linked_list* list, char* line, int line_count)
|
static int check_cmd_addr(const char* cmd, struct linked_list* list, char* line, int line_count)
|
||||||
{
|
{
|
||||||
char* data;
|
char* data1;
|
||||||
struct ip_range* range = 0;
|
char* data2;
|
||||||
|
struct ip_ban_record* info = 0;
|
||||||
|
int cidr_bits = 0;
|
||||||
|
|
||||||
if (!strncmp(line, cmd, strlen(cmd)))
|
if (!strncmp(line, cmd, strlen(cmd)))
|
||||||
{
|
{
|
||||||
data = &line[strlen(cmd)];
|
data1 = &line[strlen(cmd)];
|
||||||
data[0] = '\0';
|
data2 = 0;
|
||||||
data++;
|
data1[0] = '\0';
|
||||||
|
data1++;
|
||||||
|
|
||||||
data = strip_white_space(data);
|
data1 = strip_white_space(data1);
|
||||||
if (!*data)
|
if (!*data1)
|
||||||
{
|
{
|
||||||
LOG_FATAL("ACL parse error on line %d", line_count);
|
hub_log(log_fatal, "ACL parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
range = hub_malloc_zero(sizeof(struct ip_range));
|
info = hub_malloc_zero(sizeof(struct ip_ban_record));
|
||||||
|
|
||||||
if (!range)
|
if (!info)
|
||||||
{
|
{
|
||||||
LOG_ERROR("ACL parse error. Out of memory!");
|
hub_log(log_error, "ACL parse error. Out of memory!");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ip_convert_address_to_range(data, range))
|
/* Extract IP-range */
|
||||||
|
data2 = strrchr(data1, '-');
|
||||||
|
if (data2)
|
||||||
{
|
{
|
||||||
add_ip_range(list, range);
|
cidr_bits = -1;
|
||||||
|
data2[0] = 0;
|
||||||
|
data2++;
|
||||||
|
|
||||||
|
if (check_ip_range(data1, data2, info) == -1)
|
||||||
|
{
|
||||||
|
hub_free(info);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_ip_range(list, info);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Extract IP-bitmask */
|
||||||
|
data2 = strrchr(data1, '/');
|
||||||
|
if (data2)
|
||||||
|
{
|
||||||
|
data2[0] = 0;
|
||||||
|
data2++;
|
||||||
|
cidr_bits = uhub_atoi(data2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cidr_bits = 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_ip_mask(data1, cidr_bits, info) == -1)
|
||||||
|
{
|
||||||
|
hub_free(info);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_ip_range(list, info);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
hub_free(range);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -185,11 +266,23 @@ static int acl_parse_line(char* line, int line_count, void* ptr_data)
|
|||||||
pos[0] = 0;
|
pos[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
line = strip_white_space(line);
|
|
||||||
if (!*line)
|
if (!*line)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
LOG_DEBUG("acl_parse_line: '%s'", line);
|
#ifdef ACL_DEBUG
|
||||||
|
hub_log(log_trace, "acl_parse_line(): '%s'", line);
|
||||||
|
#endif
|
||||||
|
line = strip_white_space(line);
|
||||||
|
|
||||||
|
if (!*line)
|
||||||
|
{
|
||||||
|
hub_log(log_fatal, "ACL parse error on line %d", line_count);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ACL_DEBUG
|
||||||
|
hub_log(log_trace, "acl_parse_line: '%s'", line);
|
||||||
|
#endif
|
||||||
|
|
||||||
ACL_ADD_USER("bot", handle->users, cred_bot);
|
ACL_ADD_USER("bot", handle->users, cred_bot);
|
||||||
ACL_ADD_USER("user_admin", handle->users, cred_admin);
|
ACL_ADD_USER("user_admin", handle->users, cred_admin);
|
||||||
@@ -203,7 +296,7 @@ static int acl_parse_line(char* line, int line_count, void* ptr_data)
|
|||||||
ACL_ADD_ADDR("deny_ip", handle->networks);
|
ACL_ADD_ADDR("deny_ip", handle->networks);
|
||||||
ACL_ADD_ADDR("nat_ip", handle->nat_override);
|
ACL_ADD_ADDR("nat_ip", handle->nat_override);
|
||||||
|
|
||||||
LOG_ERROR("Unknown ACL command on line %d: '%s'", line_count, line);
|
hub_log(log_error, "Unknown ACL command on line %d: '%s'", line_count, line);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +315,7 @@ int acl_initialize(struct hub_config* config, struct acl_handle* handle)
|
|||||||
|
|
||||||
if (!handle->users || !handle->cids || !handle->networks || !handle->users_denied || !handle->users_banned || !handle->nat_override)
|
if (!handle->users || !handle->cids || !handle->networks || !handle->users_denied || !handle->users_banned || !handle->nat_override)
|
||||||
{
|
{
|
||||||
LOG_FATAL("acl_initialize: Out of memory");
|
hub_log(log_fatal, "acl_initialize: Out of memory");
|
||||||
|
|
||||||
list_destroy(handle->users);
|
list_destroy(handle->users);
|
||||||
list_destroy(handle->users_denied);
|
list_destroy(handle->users_denied);
|
||||||
@@ -247,7 +340,7 @@ int acl_initialize(struct hub_config* config, struct acl_handle* handle)
|
|||||||
|
|
||||||
static void acl_free_access_info(void* ptr)
|
static void acl_free_access_info(void* ptr)
|
||||||
{
|
{
|
||||||
struct hub_user_access_info* info = (struct hub_user_access_info*) ptr;
|
struct user_access_info* info = (struct user_access_info*) ptr;
|
||||||
if (info)
|
if (info)
|
||||||
{
|
{
|
||||||
hub_free(info->username);
|
hub_free(info->username);
|
||||||
@@ -311,22 +404,22 @@ int acl_shutdown(struct acl_handle* handle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name)
|
struct user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name)
|
||||||
{
|
{
|
||||||
struct hub_user_access_info* info = (struct hub_user_access_info*) list_get_first(handle->users);
|
struct user_access_info* info = (struct user_access_info*) list_get_first(handle->users);
|
||||||
while (info)
|
while (info)
|
||||||
{
|
{
|
||||||
if (strcasecmp(info->username, name) == 0)
|
if (strcasecmp(info->username, name) == 0)
|
||||||
{
|
{
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
info = (struct hub_user_access_info*) list_get_next(handle->users);
|
info = (struct user_access_info*) list_get_next(handle->users);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define STR_LIST_CONTAINS(LIST, STR) \
|
#define STR_LIST_CONTAINS(LIST, STR) \
|
||||||
str = (char*) list_get_first(LIST); \
|
char* str = (char*) list_get_first(LIST); \
|
||||||
while (str) \
|
while (str) \
|
||||||
{ \
|
{ \
|
||||||
if (strcasecmp(str, STR) == 0) \
|
if (strcasecmp(str, STR) == 0) \
|
||||||
@@ -337,94 +430,35 @@ struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, cons
|
|||||||
|
|
||||||
int acl_is_cid_banned(struct acl_handle* handle, const char* data)
|
int acl_is_cid_banned(struct acl_handle* handle, const char* data)
|
||||||
{
|
{
|
||||||
char* str;
|
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
STR_LIST_CONTAINS(handle->cids, data);
|
STR_LIST_CONTAINS(handle->cids, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int acl_is_user_banned(struct acl_handle* handle, const char* data)
|
int acl_is_user_banned(struct acl_handle* handle, const char* data)
|
||||||
{
|
{
|
||||||
char* str;
|
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
STR_LIST_CONTAINS(handle->users_banned, data);
|
STR_LIST_CONTAINS(handle->users_banned, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int acl_is_user_denied(struct acl_handle* handle, const char* data)
|
int acl_is_user_denied(struct acl_handle* handle, const char* data)
|
||||||
{
|
{
|
||||||
char* str;
|
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
STR_LIST_CONTAINS(handle->users_denied, data);
|
STR_LIST_CONTAINS(handle->users_denied, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int acl_user_ban_nick(struct acl_handle* handle, const char* nick)
|
|
||||||
{
|
|
||||||
char* data = 0;
|
|
||||||
struct hub_user_access_info* info = hub_malloc_zero(sizeof(struct hub_user_access_info));
|
|
||||||
|
|
||||||
if (!info)
|
|
||||||
{
|
|
||||||
LOG_ERROR("ACL error: Out of memory!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = hub_strdup(nick);
|
|
||||||
if (!data)
|
|
||||||
{
|
|
||||||
LOG_ERROR("ACL error: Out of memory!");
|
|
||||||
hub_free(info);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_append(handle->users_banned, data);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int acl_user_ban_cid(struct acl_handle* handle, const char* cid)
|
|
||||||
{
|
|
||||||
char* data;
|
|
||||||
struct hub_user_access_info* info = hub_malloc_zero(sizeof(struct hub_user_access_info));
|
|
||||||
if (!info)
|
|
||||||
{
|
|
||||||
LOG_ERROR("ACL error: Out of memory!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = hub_strdup(cid);
|
|
||||||
if (!data)
|
|
||||||
{
|
|
||||||
LOG_ERROR("ACL error: Out of memory!");
|
|
||||||
hub_free(info);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_append(handle->cids, data);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int acl_user_unban_nick(struct acl_handle* handle, const char* nick)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int acl_user_unban_cid(struct acl_handle* handle, const char* cid)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address)
|
int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address)
|
||||||
{
|
{
|
||||||
struct ip_addr_encap raw;
|
struct ip_addr_encap raw;
|
||||||
struct ip_range* info = (struct ip_range*) list_get_first(handle->networks);
|
struct ip_ban_record* info = (struct ip_ban_record*) list_get_first(handle->networks);
|
||||||
ip_convert_to_binary(ip_address, &raw);
|
ip_convert_to_binary(ip_address, &raw);
|
||||||
|
|
||||||
while (info)
|
while (info)
|
||||||
{
|
{
|
||||||
if (ip_in_range(&raw, info))
|
if (acl_check_ip_range(&raw, info))
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
info = (struct ip_range*) list_get_next(handle->networks);
|
info = (struct ip_ban_record*) list_get_next(handle->networks);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -432,63 +466,71 @@ int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address)
|
|||||||
int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address)
|
int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address)
|
||||||
{
|
{
|
||||||
struct ip_addr_encap raw;
|
struct ip_addr_encap raw;
|
||||||
struct ip_range* info = (struct ip_range*) list_get_first(handle->nat_override);
|
struct ip_ban_record* info = (struct ip_ban_record*) list_get_first(handle->nat_override);
|
||||||
ip_convert_to_binary(ip_address, &raw);
|
ip_convert_to_binary(ip_address, &raw);
|
||||||
|
|
||||||
while (info)
|
while (info)
|
||||||
{
|
{
|
||||||
if (ip_in_range(&raw, info))
|
if (acl_check_ip_range(&raw, info))
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
info = (struct ip_range*) list_get_next(handle->nat_override);
|
info = (struct ip_ban_record*) list_get_next(handle->nat_override);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int acl_check_ip_range(struct ip_addr_encap* addr, struct ip_ban_record* info)
|
||||||
|
{
|
||||||
|
return (addr->af == info->lo.af && ip_compare(&info->lo, addr) <= 0 && ip_compare(addr, &info->hi) <= 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This will generate the same challenge to the same user, always.
|
* This will generate the same challenge to the same user, always.
|
||||||
* The challenge is made up of the time of the user connected
|
* The challenge is made up of the time of the user connected
|
||||||
* seconds since the unix epoch (modulus 1 million)
|
* seconds since the unix epoch (modulus 1 million)
|
||||||
* and the SID of the user (0-1 million).
|
* and the SID of the user (0-1 million).
|
||||||
*/
|
*/
|
||||||
const char* acl_password_generate_challenge(struct acl_handle* acl, struct hub_user* user)
|
const char* password_generate_challenge(struct user* user)
|
||||||
{
|
{
|
||||||
char buf[64];
|
char buf[32];
|
||||||
uint64_t tiger_res[3];
|
uint64_t tiger_res[3];
|
||||||
static char tiger_buf[MAX_CID_LEN+1];
|
static char tiger_buf[MAX_CID_LEN+1];
|
||||||
|
|
||||||
// FIXME: Generate a better nonce scheme.
|
snprintf(buf, 32, "%d%d%d", (int) user->tm_connected, (int) user->id.sid, (int) user->sd);
|
||||||
snprintf(buf, 64, "%p%d%d", user, (int) user->id.sid, (int) net_con_get_sd(user->connection));
|
|
||||||
|
|
||||||
tiger((uint64_t*) buf, strlen(buf), (uint64_t*) tiger_res);
|
tiger((uint64_t*) buf, strlen(buf), (uint64_t*) tiger_res);
|
||||||
base32_encode((unsigned char*) tiger_res, TIGERSIZE, tiger_buf);
|
base32_encode((unsigned char*) tiger_res, TIGERSIZE, tiger_buf);
|
||||||
tiger_buf[MAX_CID_LEN] = 0;
|
tiger_buf[MAX_CID_LEN] = 0;
|
||||||
|
|
||||||
|
#ifdef ACL_DEBUG
|
||||||
|
hub_log(log_trace, "Generating challenge for user %s: '%s'", user->id.nick, tiger_buf);
|
||||||
|
#endif
|
||||||
return (const char*) tiger_buf;
|
return (const char*) tiger_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int acl_password_verify(struct acl_handle* acl, struct hub_user* user, const char* password)
|
int password_verify(struct user* user, const char* password)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
struct hub_user_access_info* access;
|
struct user_access_info* access;
|
||||||
const char* challenge;
|
const char* challenge;
|
||||||
char raw_challenge[64];
|
char raw_challenge[64];
|
||||||
char password_calc[64];
|
char password_calc[64];
|
||||||
uint64_t tiger_res[3];
|
uint64_t tiger_res[3];
|
||||||
|
|
||||||
if (!password || !user || strlen(password) != MAX_CID_LEN)
|
if (!password || !user || strlen(password) != MAX_CID_LEN)
|
||||||
return 0;
|
return password_invalid;
|
||||||
|
|
||||||
access = acl_get_access_info(acl, user->id.nick);
|
access = acl_get_access_info(user->hub->acl, user->id.nick);
|
||||||
if (!access || !access->password)
|
if (!access || !access->password)
|
||||||
return 0;
|
return password_invalid;
|
||||||
|
|
||||||
if (TIGERSIZE+strlen(access->password) >= 1024)
|
if (TIGERSIZE+strlen(access->password) >= 1024)
|
||||||
return 0;
|
return password_invalid;
|
||||||
|
|
||||||
challenge = acl_password_generate_challenge(acl, user);
|
challenge = password_generate_challenge(user);
|
||||||
|
|
||||||
base32_decode(challenge, (unsigned char*) raw_challenge, MAX_CID_LEN);
|
base32_decode(challenge, (unsigned char*) raw_challenge, MAX_CID_LEN);
|
||||||
|
|
||||||
@@ -499,11 +541,14 @@ int acl_password_verify(struct acl_handle* acl, struct hub_user* user, const cha
|
|||||||
base32_encode((unsigned char*) tiger_res, TIGERSIZE, password_calc);
|
base32_encode((unsigned char*) tiger_res, TIGERSIZE, password_calc);
|
||||||
password_calc[MAX_CID_LEN] = 0;
|
password_calc[MAX_CID_LEN] = 0;
|
||||||
|
|
||||||
|
#ifdef ACL_DEBUG
|
||||||
|
hub_log(log_trace, "Checking password %s against %s", password, password_calc);
|
||||||
|
#endif
|
||||||
if (strcasecmp(password, password_calc) == 0)
|
if (strcasecmp(password, password_calc) == 0)
|
||||||
{
|
{
|
||||||
return 1;
|
return password_ok;
|
||||||
}
|
}
|
||||||
return 0;
|
return password_invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -21,9 +21,21 @@
|
|||||||
#define HAVE_UHUB_ACL_H
|
#define HAVE_UHUB_ACL_H
|
||||||
|
|
||||||
struct hub_config;
|
struct hub_config;
|
||||||
struct hub_user;
|
struct user;
|
||||||
struct ip_addr_encap;
|
struct ip_addr_encap;
|
||||||
|
|
||||||
|
enum password_status
|
||||||
|
{
|
||||||
|
password_invalid = 0,
|
||||||
|
password_ok = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum acl_status
|
||||||
|
{
|
||||||
|
acl_not_found = 0,
|
||||||
|
acl_found = 1,
|
||||||
|
};
|
||||||
|
|
||||||
enum user_credentials
|
enum user_credentials
|
||||||
{
|
{
|
||||||
cred_none, /**<<< "User has no credentials (not yet logged in)" */
|
cred_none, /**<<< "User has no credentials (not yet logged in)" */
|
||||||
@@ -38,13 +50,19 @@ enum user_credentials
|
|||||||
|
|
||||||
const char* get_user_credential_string(enum user_credentials cred);
|
const char* get_user_credential_string(enum user_credentials cred);
|
||||||
|
|
||||||
struct hub_user_access_info
|
struct user_access_info
|
||||||
{
|
{
|
||||||
char* username; /* name of user, cid or IP range */
|
char* username; /* name of user, cid or IP range */
|
||||||
char* password; /* password */
|
char* password; /* password */
|
||||||
enum user_credentials status;
|
enum user_credentials status;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ip_ban_record
|
||||||
|
{
|
||||||
|
struct ip_addr_encap lo;
|
||||||
|
struct ip_addr_encap hi;
|
||||||
|
};
|
||||||
|
|
||||||
struct acl_handle
|
struct acl_handle
|
||||||
{
|
{
|
||||||
struct linked_list* users; /* Known users. See enum user_status */
|
struct linked_list* users; /* Known users. See enum user_status */
|
||||||
@@ -59,7 +77,7 @@ struct acl_handle
|
|||||||
extern int acl_initialize(struct hub_config* config, struct acl_handle* handle);
|
extern int acl_initialize(struct hub_config* config, struct acl_handle* handle);
|
||||||
extern int acl_shutdown(struct acl_handle* handle);
|
extern int acl_shutdown(struct acl_handle* handle);
|
||||||
|
|
||||||
extern struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name);
|
extern struct user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name);
|
||||||
extern int acl_is_cid_banned(struct acl_handle* handle, const char* cid);
|
extern int acl_is_cid_banned(struct acl_handle* handle, const char* cid);
|
||||||
extern int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address);
|
extern int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address);
|
||||||
extern int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address);
|
extern int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address);
|
||||||
@@ -67,19 +85,9 @@ extern int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_addr
|
|||||||
extern int acl_is_user_banned(struct acl_handle* handle, const char* name);
|
extern int acl_is_user_banned(struct acl_handle* handle, const char* name);
|
||||||
extern int acl_is_user_denied(struct acl_handle* handle, const char* name);
|
extern int acl_is_user_denied(struct acl_handle* handle, const char* name);
|
||||||
|
|
||||||
extern int acl_user_ban_nick(struct acl_handle* handle, const char* nick);
|
extern int acl_check_ip_range(struct ip_addr_encap* addr, struct ip_ban_record* info);
|
||||||
extern int acl_user_ban_cid(struct acl_handle* handle, const char* cid);
|
|
||||||
extern int acl_user_unban_nick(struct acl_handle* handle, const char* nick);
|
|
||||||
extern int acl_user_unban_cid(struct acl_handle* handle, const char* cid);
|
|
||||||
|
|
||||||
extern const char* acl_password_generate_challenge(struct acl_handle* acl, struct hub_user* user);
|
extern const char* password_generate_challenge(struct user* user);
|
||||||
|
extern int password_verify(struct user* user, const char* password);
|
||||||
/**
|
|
||||||
* Verify a password.
|
|
||||||
*
|
|
||||||
* @param password the hashed password (based on the nonce).
|
|
||||||
* @return 1 if the password matches, or 0 if the password is incorrect.
|
|
||||||
*/
|
|
||||||
extern int acl_password_verify(struct acl_handle* acl, struct hub_user* user, const char* password);
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_ACL_H */
|
#endif /* HAVE_UHUB_ACL_H */
|
||||||
218
src/commands.c
Normal file
218
src/commands.c
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
typedef int (*command_handler)(struct hub_info* hub, struct user* user, const char* message);
|
||||||
|
|
||||||
|
struct commands_handler
|
||||||
|
{
|
||||||
|
const char* prefix;
|
||||||
|
size_t length;
|
||||||
|
enum user_credentials cred;
|
||||||
|
command_handler handler;
|
||||||
|
const char* description;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct commands_handler command_handlers[];
|
||||||
|
|
||||||
|
static void send_message(struct hub_info* hub, struct user* user, const char* message)
|
||||||
|
{
|
||||||
|
char* buffer = adc_msg_escape(message);
|
||||||
|
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||||
|
adc_msg_add_argument(command, buffer);
|
||||||
|
route_to_user(user, command);
|
||||||
|
adc_msg_free(command);
|
||||||
|
hub_free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int command_access_denied(struct hub_info* hub, struct user* user, const char* command)
|
||||||
|
{
|
||||||
|
char temp[128];
|
||||||
|
snprintf(temp, 128, "*** Access denied: \"%s\"", command);
|
||||||
|
send_message(hub, user, temp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int command_not_found(struct hub_info* hub, struct user* user, const char* command)
|
||||||
|
{
|
||||||
|
char temp[128];
|
||||||
|
snprintf(temp, 128, "*** Command not found: \"%s\"", command);
|
||||||
|
send_message(hub, user, temp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int command_status(struct hub_info* hub, struct user* user, const char* command, const char* message)
|
||||||
|
{
|
||||||
|
char temp[1024];
|
||||||
|
snprintf(temp, 1024, "*** %s: %s", command, message);
|
||||||
|
send_message(hub, user, temp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int command_stats(struct hub_info* hub, struct user* user, const char* message)
|
||||||
|
{
|
||||||
|
char temp[128];
|
||||||
|
snprintf(temp, 128, "%zu users, peak: %zu. Network (up/down): %d/%d KB/s, peak: %d/%d KB/s",
|
||||||
|
hub->users->count,
|
||||||
|
hub->users->count_peak,
|
||||||
|
(int) hub->stats.net_tx / 1024,
|
||||||
|
(int) hub->stats.net_rx / 1024,
|
||||||
|
(int) hub->stats.net_tx_peak / 1024,
|
||||||
|
(int) hub->stats.net_rx_peak / 1024);
|
||||||
|
|
||||||
|
return command_status(hub, user, "stats", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int command_help(struct hub_info* hub, struct user* user, const char* message)
|
||||||
|
{
|
||||||
|
#define MAX_HELP_MSG 1024
|
||||||
|
size_t n;
|
||||||
|
char msg[MAX_HELP_MSG];
|
||||||
|
msg[0] = 0;
|
||||||
|
strcat(msg, "Available commands:\n");
|
||||||
|
|
||||||
|
for (n = 0; command_handlers[n].prefix; n++)
|
||||||
|
{
|
||||||
|
if (command_handlers[n].cred <= user->credentials)
|
||||||
|
{
|
||||||
|
strcat(msg, "!");
|
||||||
|
strcat(msg, command_handlers[n].prefix);
|
||||||
|
strcat(msg, " - ");
|
||||||
|
strcat(msg, command_handlers[n].description);
|
||||||
|
strcat(msg, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return command_status(hub, user, "help", msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int command_uptime(struct hub_info* hub, struct user* user, const char* message)
|
||||||
|
{
|
||||||
|
char tmp[128];
|
||||||
|
size_t d;
|
||||||
|
size_t h;
|
||||||
|
size_t m;
|
||||||
|
size_t D = (size_t) difftime(time(0), hub->tm_started);
|
||||||
|
|
||||||
|
d = D / (24 * 3600);
|
||||||
|
D = D % (24 * 3600);
|
||||||
|
h = D / 3600;
|
||||||
|
D = D % 3600;
|
||||||
|
m = D / 60;
|
||||||
|
|
||||||
|
tmp[0] = 0;
|
||||||
|
if (d)
|
||||||
|
{
|
||||||
|
strcat(tmp, uhub_itoa((int) d));
|
||||||
|
strcat(tmp, " day");
|
||||||
|
if (d != 1) strcat(tmp, "s");
|
||||||
|
strcat(tmp, ", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h < 10) strcat(tmp, "0");
|
||||||
|
strcat(tmp, uhub_itoa((int) h));
|
||||||
|
strcat(tmp, ":");
|
||||||
|
if (m < 10) strcat(tmp, "0");
|
||||||
|
strcat(tmp, uhub_itoa((int) m));
|
||||||
|
|
||||||
|
return command_status(hub, user, "uptime", tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int command_kick(struct hub_info* hub, struct user* user, const char* message)
|
||||||
|
{
|
||||||
|
if (strlen(message) < 7)
|
||||||
|
{
|
||||||
|
return command_status(hub, user, "kick", "No nickname given");
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* nick = &message[7];
|
||||||
|
struct user* target = uman_get_user_by_nick(hub, nick);
|
||||||
|
|
||||||
|
if (!target)
|
||||||
|
{
|
||||||
|
return command_status(hub, user, "kick", "No such user");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target == user)
|
||||||
|
{
|
||||||
|
return command_status(hub, user, "kick", "Cannot kick yourself");
|
||||||
|
}
|
||||||
|
|
||||||
|
user_disconnect(target, quit_kicked);
|
||||||
|
return command_status(hub, user, "kick", nick);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int command_reload(struct hub_info* hub, struct user* user, const char* message)
|
||||||
|
{
|
||||||
|
hub->status = hub_status_restart;
|
||||||
|
return command_status(hub, user, "reload", "Reloading configuration...");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int command_shutdown(struct hub_info* hub, struct user* user, const char* message)
|
||||||
|
{
|
||||||
|
hub->status = hub_status_shutdown;
|
||||||
|
return command_status(hub, user, "shutdown", "Hub shutting down...");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int command_version(struct hub_info* hub, struct user* user, const char* message)
|
||||||
|
{
|
||||||
|
return command_status(hub, user, "version", "Powered by " PRODUCT "/" VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int command_myip(struct hub_info* hub, struct user* user, const char* message)
|
||||||
|
{
|
||||||
|
char tmp[128];
|
||||||
|
snprintf(tmp, 128, "Your IP is \"%s\"", ip_convert_to_string(&user->ipaddr));
|
||||||
|
return command_status(hub, user, "myip", tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int command_dipatcher(struct hub_info* hub, struct user* user, const char* message)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
for (n = 0; command_handlers[n].prefix; n++)
|
||||||
|
{
|
||||||
|
if (!strncmp(message, command_handlers[n].prefix, command_handlers[n].length))
|
||||||
|
{
|
||||||
|
if (command_handlers[n].cred <= user->credentials)
|
||||||
|
{
|
||||||
|
return command_handlers[n].handler(hub, user, message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return command_access_denied(hub, user, command_handlers[n].prefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command_not_found(hub, user, message);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct commands_handler command_handlers[] = {
|
||||||
|
{ "help", 4, cred_guest, command_help, "Show this help message." },
|
||||||
|
{ "stats", 5, cred_super, command_stats, "Show hub statistics." },
|
||||||
|
{ "version", 7, cred_guest, command_version, "Show hub version info." },
|
||||||
|
{ "uptime", 6, cred_guest, command_uptime, "Display hub uptime info." },
|
||||||
|
{ "kick", 4, cred_operator, command_kick, "Kick a user" },
|
||||||
|
{ "reload", 6, cred_admin, command_reload, "Reload configuration files." },
|
||||||
|
{ "shutdown", 8, cred_admin, command_shutdown, "Shutdown hub." },
|
||||||
|
{ "myip", 4, cred_guest, command_myip, "Show your own IP." },
|
||||||
|
{ 0, 0, cred_none, command_help, "" }
|
||||||
|
};
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -19,4 +19,17 @@
|
|||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
|
|
||||||
extern int command_dipatcher(struct hub_info* hub, struct hub_user* user, const char* message);
|
#define CHAT_MSG_HANDLED 1
|
||||||
|
#define CHAT_MSG_IGNORED 0
|
||||||
|
#define CHAT_MSG_INVALID -1
|
||||||
|
|
||||||
|
typedef int (*plugin_event_chat_message)(struct hub_info*, struct user*, struct adc_message*);
|
||||||
|
|
||||||
|
struct command_info
|
||||||
|
{
|
||||||
|
const char* prefix;
|
||||||
|
enum user_credentials cred;
|
||||||
|
plugin_event_chat_message function;
|
||||||
|
};
|
||||||
|
|
||||||
|
int command_dipatcher(struct hub_info* hub, struct user* user, const char* message);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
else if (strncasecmp(data, "off", 3) == 0) TARGET = 0; \
|
else if (strncasecmp(data, "off", 3) == 0) TARGET = 0; \
|
||||||
else\
|
else\
|
||||||
{ \
|
{ \
|
||||||
LOG_FATAL("Configuration error on line %d: '%s' must be either '1' or '0'", line_count, key); \
|
hub_log(log_fatal, "Configuration error on line %d: '%s' must be either '1' or '0'", line_count, key); \
|
||||||
return -1; \
|
return -1; \
|
||||||
} \
|
} \
|
||||||
TARGET |= 0x80000000; \
|
TARGET |= 0x80000000; \
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
errno = 0; \
|
errno = 0; \
|
||||||
val = strtol(data, &endptr, 10); \
|
val = strtol(data, &endptr, 10); \
|
||||||
if (((errno == ERANGE && (val == INT_MAX || val == INT_MIN)) || (errno != 0 && val == 0)) || endptr == data) { \
|
if (((errno == ERANGE && (val == INT_MAX || val == INT_MIN)) || (errno != 0 && val == 0)) || endptr == data) { \
|
||||||
LOG_FATAL("Configuration error on line %d: '%s' must be a number", line_count, key); \
|
hub_log(log_fatal, "Configuration error on line %d: '%s' must be a number", line_count, key); \
|
||||||
return -1; \
|
return -1; \
|
||||||
} \
|
} \
|
||||||
TARGET = val; \
|
TARGET = val; \
|
||||||
@@ -103,31 +103,24 @@
|
|||||||
#define IGNORED(NAME) \
|
#define IGNORED(NAME) \
|
||||||
if (strcmp(#NAME, key) == 0) \
|
if (strcmp(#NAME, key) == 0) \
|
||||||
{ \
|
{ \
|
||||||
LOG_WARN("Configuration option %s deprecated and ingnored.", key); \
|
hub_log(log_warning, "Configuration option %s deprecated and ingnored.", key); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
/* default configuration values */
|
/* default configuration values */
|
||||||
#define DEF_SERVER_BIND_ADDR "any"
|
#define DEF_SERVER_BIND_ADDR "any"
|
||||||
#define DEF_SERVER_PORT 1511
|
#define DEF_SERVER_PORT 1511
|
||||||
#define DEF_SERVER_BACKLOG 50
|
|
||||||
#define DEF_SERVER_ALT_PORTS ""
|
|
||||||
#define DEF_HUB_NAME "uhub"
|
#define DEF_HUB_NAME "uhub"
|
||||||
#define DEF_HUB_DESCRIPTION ""
|
#define DEF_HUB_DESCRIPTION ""
|
||||||
#define DEF_HUB_ENABLED 1
|
#define DEF_HUB_ENABLED 1
|
||||||
#define DEF_FILE_ACL ""
|
#define DEF_FILE_ACL ""
|
||||||
#define DEF_FILE_MOTD ""
|
#define DEF_FILE_MOTD ""
|
||||||
#define DEF_FILE_RULES ""
|
|
||||||
#define DEF_MAX_USERS 500
|
#define DEF_MAX_USERS 500
|
||||||
#define DEF_MAX_CHAT_HISTORY 20
|
|
||||||
#define DEF_MAX_LOGOUT_LOG 100
|
|
||||||
#define DEF_MAX_RECV_BUFFER 4096
|
#define DEF_MAX_RECV_BUFFER 4096
|
||||||
#define DEF_MAX_SEND_BUFFER 131072
|
#define DEF_MAX_SEND_BUFFER 131072
|
||||||
#define DEF_MAX_SEND_BUFFER_SOFT 98304
|
#define DEF_MAX_SEND_BUFFER_SOFT 98304
|
||||||
#define DEF_SHOW_BANNER 1
|
#define DEF_SHOW_BANNER 1
|
||||||
#define DEF_SHOW_BANNER_SYS_INFO 1
|
|
||||||
#define DEF_REGISTERED_USERS_ONLY 0
|
#define DEF_REGISTERED_USERS_ONLY 0
|
||||||
#define DEF_OBSOLETE_CLIENTS 0
|
|
||||||
#define DEF_CHAT_ONLY 0
|
#define DEF_CHAT_ONLY 0
|
||||||
#define DEF_CHAT_IS_PRIVILEGED 0
|
#define DEF_CHAT_IS_PRIVILEGED 0
|
||||||
#define DEF_LOW_BANDWIDTH_MODE 0
|
#define DEF_LOW_BANDWIDTH_MODE 0
|
||||||
@@ -142,10 +135,6 @@
|
|||||||
#define DEF_LIMIT_MAX_SHARE 0
|
#define DEF_LIMIT_MAX_SHARE 0
|
||||||
#define DEF_LIMIT_MIN_SLOTS 0
|
#define DEF_LIMIT_MIN_SLOTS 0
|
||||||
#define DEF_LIMIT_MAX_SLOTS 0
|
#define DEF_LIMIT_MAX_SLOTS 0
|
||||||
#define DEF_TLS_ENABLE 0
|
|
||||||
#define DEF_TLS_REQUIRE 1
|
|
||||||
#define DEF_TLS_PRIVATE_KEY ""
|
|
||||||
#define DEF_TLS_CERTIFICATE ""
|
|
||||||
#define DEF_MSG_HUB_FULL "Hub is full"
|
#define DEF_MSG_HUB_FULL "Hub is full"
|
||||||
#define DEF_MSG_HUB_DISABLED "Hub is disabled"
|
#define DEF_MSG_HUB_DISABLED "Hub is disabled"
|
||||||
#define DEF_MSG_HUB_REGISTERED_USERS_ONLY "Hub is for registered users only"
|
#define DEF_MSG_HUB_REGISTERED_USERS_ONLY "Hub is for registered users only"
|
||||||
@@ -175,8 +164,6 @@
|
|||||||
#define DEF_MSG_USER_SLOTS_HIGH "User have too many upload slots."
|
#define DEF_MSG_USER_SLOTS_HIGH "User have too many upload slots."
|
||||||
#define DEF_MSG_USER_HUB_LIMIT_LOW "User is on too few hubs."
|
#define DEF_MSG_USER_HUB_LIMIT_LOW "User is on too few hubs."
|
||||||
#define DEF_MSG_USER_HUB_LIMIT_HIGH "User is on too many hubs."
|
#define DEF_MSG_USER_HUB_LIMIT_HIGH "User is on too many hubs."
|
||||||
#define DEF_MSG_PROTO_NO_COMMON_HASH "No common hash algorithm."
|
|
||||||
#define DEF_MSG_PROTO_OBSOLETE_ADC0 "Your client does not support ADC/1.0."
|
|
||||||
|
|
||||||
void config_defaults(struct hub_config* config)
|
void config_defaults(struct hub_config* config)
|
||||||
{
|
{
|
||||||
@@ -186,19 +173,12 @@ void config_defaults(struct hub_config* config)
|
|||||||
DEFAULT_BOOLEAN(hub_enabled, DEF_HUB_ENABLED);
|
DEFAULT_BOOLEAN(hub_enabled, DEF_HUB_ENABLED);
|
||||||
DEFAULT_STRING (file_acl, DEF_FILE_ACL);
|
DEFAULT_STRING (file_acl, DEF_FILE_ACL);
|
||||||
DEFAULT_STRING (file_motd, DEF_FILE_MOTD);
|
DEFAULT_STRING (file_motd, DEF_FILE_MOTD);
|
||||||
DEFAULT_STRING (file_rules, DEF_FILE_RULES);
|
|
||||||
DEFAULT_INTEGER(server_port, DEF_SERVER_PORT);
|
DEFAULT_INTEGER(server_port, DEF_SERVER_PORT);
|
||||||
DEFAULT_INTEGER(server_listen_backlog, DEF_SERVER_BACKLOG);
|
|
||||||
DEFAULT_STRING (server_alt_ports, DEF_SERVER_ALT_PORTS);
|
|
||||||
DEFAULT_INTEGER(max_users, DEF_MAX_USERS);
|
DEFAULT_INTEGER(max_users, DEF_MAX_USERS);
|
||||||
DEFAULT_INTEGER(max_chat_history, DEF_MAX_CHAT_HISTORY);
|
|
||||||
DEFAULT_INTEGER(max_logout_log, DEF_MAX_LOGOUT_LOG);
|
|
||||||
DEFAULT_INTEGER(max_recv_buffer, DEF_MAX_RECV_BUFFER);
|
DEFAULT_INTEGER(max_recv_buffer, DEF_MAX_RECV_BUFFER);
|
||||||
DEFAULT_INTEGER(max_send_buffer, DEF_MAX_SEND_BUFFER);
|
DEFAULT_INTEGER(max_send_buffer, DEF_MAX_SEND_BUFFER);
|
||||||
DEFAULT_INTEGER(max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
|
DEFAULT_INTEGER(max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
|
||||||
DEFAULT_BOOLEAN(show_banner, DEF_SHOW_BANNER);
|
DEFAULT_BOOLEAN(show_banner, DEF_SHOW_BANNER);
|
||||||
DEFAULT_BOOLEAN(show_banner_sys_info, DEF_SHOW_BANNER_SYS_INFO);
|
|
||||||
DEFAULT_BOOLEAN(obsolete_clients, DEF_OBSOLETE_CLIENTS);
|
|
||||||
DEFAULT_BOOLEAN(chat_only, DEF_CHAT_ONLY);
|
DEFAULT_BOOLEAN(chat_only, DEF_CHAT_ONLY);
|
||||||
DEFAULT_BOOLEAN(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
|
DEFAULT_BOOLEAN(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
|
||||||
DEFAULT_BOOLEAN(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
|
DEFAULT_BOOLEAN(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
|
||||||
@@ -247,13 +227,11 @@ void config_defaults(struct hub_config* config)
|
|||||||
DEFAULT_STRING (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
|
DEFAULT_STRING (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
|
||||||
DEFAULT_STRING (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
|
DEFAULT_STRING (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
|
||||||
DEFAULT_STRING (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
|
DEFAULT_STRING (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
|
||||||
DEFAULT_STRING (msg_proto_no_common_hash, DEF_MSG_PROTO_NO_COMMON_HASH);
|
|
||||||
DEFAULT_STRING (msg_proto_obsolete_adc0, DEF_MSG_PROTO_OBSOLETE_ADC0);
|
|
||||||
|
|
||||||
DEFAULT_INTEGER(tls_enable, DEF_TLS_ENABLE);
|
DEFAULT_INTEGER(tls_enable, 0);
|
||||||
DEFAULT_INTEGER(tls_require, DEF_TLS_REQUIRE);
|
DEFAULT_INTEGER(tls_require, 0);
|
||||||
DEFAULT_STRING (tls_certificate, DEF_TLS_CERTIFICATE);
|
DEFAULT_STRING (tls_certificate, "");
|
||||||
DEFAULT_STRING (tls_private_key, DEF_TLS_PRIVATE_KEY);
|
DEFAULT_STRING (tls_private_key, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -261,23 +239,16 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
{
|
{
|
||||||
GET_STR (file_acl);
|
GET_STR (file_acl);
|
||||||
GET_STR (file_motd);
|
GET_STR (file_motd);
|
||||||
GET_STR (file_rules);
|
|
||||||
GET_STR (server_bind_addr);
|
GET_STR (server_bind_addr);
|
||||||
GET_INT (server_port);
|
GET_INT (server_port);
|
||||||
GET_INT (server_listen_backlog);
|
|
||||||
GET_STR (server_alt_ports);
|
|
||||||
GET_STR (hub_name);
|
GET_STR (hub_name);
|
||||||
GET_STR (hub_description);
|
GET_STR (hub_description);
|
||||||
GET_BOOL(hub_enabled);
|
GET_BOOL(hub_enabled);
|
||||||
GET_INT (max_users);
|
GET_INT (max_users);
|
||||||
GET_INT (max_chat_history);
|
|
||||||
GET_INT (max_logout_log);
|
|
||||||
GET_INT (max_recv_buffer);
|
GET_INT (max_recv_buffer);
|
||||||
GET_INT (max_send_buffer);
|
GET_INT (max_send_buffer);
|
||||||
GET_INT (max_send_buffer_soft);
|
GET_INT (max_send_buffer_soft);
|
||||||
GET_BOOL(show_banner);
|
GET_BOOL(show_banner);
|
||||||
GET_BOOL(show_banner_sys_info);
|
|
||||||
GET_BOOL(obsolete_clients);
|
|
||||||
GET_BOOL(chat_only);
|
GET_BOOL(chat_only);
|
||||||
GET_BOOL(chat_is_privileged);
|
GET_BOOL(chat_is_privileged);
|
||||||
GET_BOOL(low_bandwidth_mode);
|
GET_BOOL(low_bandwidth_mode);
|
||||||
@@ -326,17 +297,14 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
GET_STR (msg_user_slots_high);
|
GET_STR (msg_user_slots_high);
|
||||||
GET_STR (msg_user_hub_limit_low);
|
GET_STR (msg_user_hub_limit_low);
|
||||||
GET_STR (msg_user_hub_limit_high);
|
GET_STR (msg_user_hub_limit_high);
|
||||||
GET_STR (msg_proto_no_common_hash);
|
|
||||||
GET_STR (msg_proto_obsolete_adc0);
|
|
||||||
|
|
||||||
/* TLS/SSL related */
|
|
||||||
GET_BOOL(tls_enable);
|
GET_BOOL(tls_enable);
|
||||||
GET_BOOL(tls_require);
|
GET_BOOL(tls_require);
|
||||||
GET_STR (tls_certificate);
|
GET_STR (tls_certificate);
|
||||||
GET_STR (tls_private_key);
|
GET_STR (tls_private_key);
|
||||||
|
|
||||||
/* Still here -- unknown directive */
|
/* Still here -- unknown directive */
|
||||||
LOG_ERROR("Unknown configuration directive: '%s'", key);
|
hub_log(log_fatal, "Unknown configuration directive: '%s'", key);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,10 +312,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
void free_config(struct hub_config* config)
|
void free_config(struct hub_config* config)
|
||||||
{
|
{
|
||||||
hub_free(config->server_bind_addr);
|
hub_free(config->server_bind_addr);
|
||||||
hub_free(config->server_alt_ports);
|
|
||||||
hub_free(config->file_motd);
|
hub_free(config->file_motd);
|
||||||
hub_free(config->file_acl);
|
hub_free(config->file_acl);
|
||||||
hub_free(config->file_rules);
|
|
||||||
hub_free(config->hub_name);
|
hub_free(config->hub_name);
|
||||||
hub_free(config->hub_description);
|
hub_free(config->hub_description);
|
||||||
|
|
||||||
@@ -380,8 +346,6 @@ void free_config(struct hub_config* config)
|
|||||||
hub_free(config->msg_user_slots_high);
|
hub_free(config->msg_user_slots_high);
|
||||||
hub_free(config->msg_user_hub_limit_low);
|
hub_free(config->msg_user_hub_limit_low);
|
||||||
hub_free(config->msg_user_hub_limit_high);
|
hub_free(config->msg_user_hub_limit_high);
|
||||||
hub_free(config->msg_proto_no_common_hash);
|
|
||||||
hub_free(config->msg_proto_obsolete_adc0);
|
|
||||||
|
|
||||||
hub_free(config->tls_certificate);
|
hub_free(config->tls_certificate);
|
||||||
hub_free(config->tls_private_key);
|
hub_free(config->tls_private_key);
|
||||||
@@ -421,35 +385,21 @@ void dump_config(struct hub_config* config, int ignore_defaults)
|
|||||||
{
|
{
|
||||||
DUMP_STR (file_acl, DEF_FILE_ACL);
|
DUMP_STR (file_acl, DEF_FILE_ACL);
|
||||||
DUMP_STR (file_motd, DEF_FILE_MOTD);
|
DUMP_STR (file_motd, DEF_FILE_MOTD);
|
||||||
DUMP_STR (file_rules, DEF_FILE_RULES);
|
|
||||||
DUMP_STR (server_bind_addr, DEF_SERVER_BIND_ADDR);
|
DUMP_STR (server_bind_addr, DEF_SERVER_BIND_ADDR);
|
||||||
DUMP_INT (server_port, DEF_SERVER_PORT);
|
DUMP_INT (server_port, DEF_SERVER_PORT);
|
||||||
DUMP_INT (server_listen_backlog, DEF_SERVER_BACKLOG);
|
|
||||||
DUMP_STR (server_alt_ports, DEF_SERVER_ALT_PORTS);
|
|
||||||
DUMP_STR (hub_name, DEF_HUB_NAME);
|
DUMP_STR (hub_name, DEF_HUB_NAME);
|
||||||
DUMP_STR (hub_description, DEF_HUB_DESCRIPTION);
|
DUMP_STR (hub_description, DEF_HUB_DESCRIPTION);
|
||||||
DUMP_BOOL(hub_enabled, DEF_HUB_ENABLED);
|
DUMP_BOOL(hub_enabled, DEF_HUB_ENABLED);
|
||||||
DUMP_INT (max_users, DEF_MAX_USERS);
|
DUMP_INT (max_users, DEF_MAX_USERS);
|
||||||
DUMP_INT (max_chat_history, DEF_MAX_CHAT_HISTORY);
|
|
||||||
DUMP_INT (max_logout_log, DEF_MAX_LOGOUT_LOG);
|
|
||||||
DUMP_INT (max_recv_buffer, DEF_MAX_RECV_BUFFER);
|
DUMP_INT (max_recv_buffer, DEF_MAX_RECV_BUFFER);
|
||||||
DUMP_INT (max_send_buffer, DEF_MAX_SEND_BUFFER);
|
DUMP_INT (max_send_buffer, DEF_MAX_SEND_BUFFER);
|
||||||
DUMP_INT (max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
|
DUMP_INT (max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
|
||||||
DUMP_BOOL(show_banner, DEF_SHOW_BANNER);
|
DUMP_BOOL(show_banner, DEF_SHOW_BANNER);
|
||||||
DUMP_BOOL(show_banner_sys_info, DEF_SHOW_BANNER_SYS_INFO);
|
|
||||||
DUMP_BOOL(obsolete_clients, DEF_OBSOLETE_CLIENTS);
|
|
||||||
DUMP_BOOL(chat_only, DEF_CHAT_ONLY);
|
DUMP_BOOL(chat_only, DEF_CHAT_ONLY);
|
||||||
DUMP_BOOL(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
|
DUMP_BOOL(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
|
||||||
DUMP_BOOL(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
|
DUMP_BOOL(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
|
||||||
DUMP_BOOL(registered_users_only, DEF_REGISTERED_USERS_ONLY);
|
DUMP_BOOL(registered_users_only, DEF_REGISTERED_USERS_ONLY);
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
DUMP_BOOL(tls_enable, DEF_TLS_ENABLE);
|
|
||||||
DUMP_BOOL(tls_require, DEF_TLS_REQUIRE);
|
|
||||||
DUMP_STR (tls_certificate, DEF_TLS_CERTIFICATE);
|
|
||||||
DUMP_STR (tls_private_key, DEF_TLS_PRIVATE_KEY);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Limits enforced on users */
|
/* Limits enforced on users */
|
||||||
DUMP_INT(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
|
DUMP_INT(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
|
||||||
DUMP_INT(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
|
DUMP_INT(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
|
||||||
@@ -493,8 +443,6 @@ void dump_config(struct hub_config* config, int ignore_defaults)
|
|||||||
DUMP_STR (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
|
DUMP_STR (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
|
||||||
DUMP_STR (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
|
DUMP_STR (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
|
||||||
DUMP_STR (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
|
DUMP_STR (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
|
||||||
DUMP_STR (msg_proto_no_common_hash, DEF_MSG_PROTO_NO_COMMON_HASH);
|
|
||||||
DUMP_STR (msg_proto_obsolete_adc0, DEF_MSG_PROTO_OBSOLETE_ADC0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -512,11 +460,13 @@ static int config_parse_line(char* line, int line_count, void* ptr_data)
|
|||||||
|
|
||||||
if (!*line) return 0;
|
if (!*line) return 0;
|
||||||
|
|
||||||
LOG_DUMP("config_parse_line(): '%s'", line);
|
#ifdef CONFIG_DUMP
|
||||||
|
hub_log(log_trace, "config_parse_line(): '%s'", line);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!is_valid_utf8(line))
|
if (!is_valid_utf8(line))
|
||||||
{
|
{
|
||||||
LOG_WARN("Invalid utf-8 characters on line %d", line_count);
|
hub_log(log_warning, "Invalid utf-8 characters on line %d", line_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pos = strchr(line, '=')) != NULL)
|
if ((pos = strchr(line, '=')) != NULL)
|
||||||
@@ -536,11 +486,13 @@ static int config_parse_line(char* line, int line_count, void* ptr_data)
|
|||||||
|
|
||||||
if (!*key || !*data)
|
if (!*key || !*data)
|
||||||
{
|
{
|
||||||
LOG_FATAL("Configuration parse error on line %d", line_count);
|
hub_log(log_fatal, "Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DUMP("config_parse_line: '%s' => '%s'", key, data);
|
#ifdef CONFIG_DUMP
|
||||||
|
hub_log(log_trace, "config_parse_line: '%s' => '%s'", key, data);
|
||||||
|
#endif
|
||||||
|
|
||||||
return apply_config(config, key, data, line_count);
|
return apply_config(config, key, data, line_count);
|
||||||
}
|
}
|
||||||
@@ -557,7 +509,7 @@ int read_config(const char* file, struct hub_config* config, int allow_missing)
|
|||||||
{
|
{
|
||||||
if (allow_missing && ret == -2)
|
if (allow_missing && ret == -2)
|
||||||
{
|
{
|
||||||
LOG_DUMP("Using default configuration.");
|
hub_log(log_debug, "Using default configuration.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -24,19 +24,14 @@ struct hub_config
|
|||||||
{
|
{
|
||||||
int server_port; /**<<< "Server port to bind to (default: 1511)" */
|
int server_port; /**<<< "Server port to bind to (default: 1511)" */
|
||||||
char* server_bind_addr; /**<<< "Server bind address (default: '0.0.0.0' or '::')" */
|
char* server_bind_addr; /**<<< "Server bind address (default: '0.0.0.0' or '::')" */
|
||||||
int server_listen_backlog; /**<<< "Server listen backlog (default: 50)" */
|
|
||||||
char* server_alt_ports; /**<<< "Comma separated list of alternative ports to listen to (default: '')" */
|
|
||||||
int hub_enabled; /**<<< "Is server enabled (default: 1)" */
|
int hub_enabled; /**<<< "Is server enabled (default: 1)" */
|
||||||
int show_banner; /**<<< "Show banner on connect (default: 1)" */
|
int show_banner; /**<<< "Show banner on connect (default: 1)" */
|
||||||
int show_banner_sys_info; /**<<< "Show banner system information (default: 1). Has no effect unless show_banner is enabled." */
|
|
||||||
int max_users; /**<<< "Maximum number of users allowed on the hub (default: 500)" */
|
int max_users; /**<<< "Maximum number of users allowed on the hub (default: 500)" */
|
||||||
int registered_users_only; /**<<< "Allow registered users only (default: 0)" */
|
int registered_users_only; /**<<< "Allow registered users only (default: 0)" */
|
||||||
int obsolete_clients; /**<<< "Support obsolete clients using a ADC protocol prior to 1.0 (default: off)" */
|
|
||||||
int chat_only; /**<<< "Allow chat only operation on hub (default: 0)" */
|
int chat_only; /**<<< "Allow chat only operation on hub (default: 0)" */
|
||||||
int chat_is_privileged; /**<<< "Allow chat for operators and above only (default: 0) */
|
int chat_is_privileged; /**<<< "Allow chat for operators and above only (default: 0) */
|
||||||
char* file_motd; /**<<< "File containing the 'message of the day' (default: '' - no motd)" */
|
char* file_motd; /**<<< "File containing the 'message of the day' (default: '' - no motd)" */
|
||||||
char* file_acl; /**<<< "File containing user database (default: '' - no known users)" */
|
char* file_acl; /**<<< "File containing user database (default: '' - no known users)" */
|
||||||
char* file_rules; /**<<< "File containing the rules (default: '' - no rules)" */
|
|
||||||
char* hub_name; /**<<< "Name of hub (default: 'My uhub hub')" */
|
char* hub_name; /**<<< "Name of hub (default: 'My uhub hub')" */
|
||||||
char* hub_description; /**<<< "Name of hub (default: 'no description')" */
|
char* hub_description; /**<<< "Name of hub (default: 'no description')" */
|
||||||
int max_recv_buffer; /**<<< "Max read buffer before parse, per user (default: 4096)" */
|
int max_recv_buffer; /**<<< "Max read buffer before parse, per user (default: 4096)" */
|
||||||
@@ -44,9 +39,6 @@ struct hub_config
|
|||||||
int max_send_buffer_soft; /**<<< "Max send buffer before message drops, per user (default: 96K)" */
|
int max_send_buffer_soft; /**<<< "Max send buffer before message drops, per user (default: 96K)" */
|
||||||
int low_bandwidth_mode; /**<<< "If this is enabled, the hub will strip off elements from each user's info message to reduce bandwidth usage" */
|
int low_bandwidth_mode; /**<<< "If this is enabled, the hub will strip off elements from each user's info message to reduce bandwidth usage" */
|
||||||
|
|
||||||
int max_chat_history; /**<<< "Number of chat messages kept in history (default: 20)" */
|
|
||||||
int max_logout_log; /**<<< "Number of log entries for people leaving the hub. (default: 100) */
|
|
||||||
|
|
||||||
/* Limits enforced on users */
|
/* Limits enforced on users */
|
||||||
int limit_max_hubs_user; /**<<< "Max concurrent hubs as a user. (0=off, default: 10)" */
|
int limit_max_hubs_user; /**<<< "Max concurrent hubs as a user. (0=off, default: 10)" */
|
||||||
int limit_max_hubs_reg; /**<<< "Max concurrent hubs as registered user. (0=off, default: 10)" */
|
int limit_max_hubs_reg; /**<<< "Max concurrent hubs as registered user. (0=off, default: 10)" */
|
||||||
@@ -90,8 +82,6 @@ struct hub_config
|
|||||||
char* msg_user_slots_high; /**<<< "User have too many upload slots." */
|
char* msg_user_slots_high; /**<<< "User have too many upload slots." */
|
||||||
char* msg_user_hub_limit_low; /**<<< "User is on too few hubs." */
|
char* msg_user_hub_limit_low; /**<<< "User is on too few hubs." */
|
||||||
char* msg_user_hub_limit_high; /**<<< "User is on too many hubs." */
|
char* msg_user_hub_limit_high; /**<<< "User is on too many hubs." */
|
||||||
char* msg_proto_no_common_hash; /**<<< "No common hash algorithm." */
|
|
||||||
char* msg_proto_obsolete_adc0; /**<<< "Client is using an obsolete ADC protocol version." */
|
|
||||||
|
|
||||||
int tls_enable; /**<<< "Enable SSL/TLS support (default: 0)" */
|
int tls_enable; /**<<< "Enable SSL/TLS support (default: 0)" */
|
||||||
int tls_require; /**<<< "If SSL/TLS enabled, should it be required (default: 0) */
|
int tls_require; /**<<< "If SSL/TLS enabled, should it be required (default: 0) */
|
||||||
@@ -1,626 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 DEBUG
|
|
||||||
#define CRASH_DEBUG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MAX_HELP_MSG 1024
|
|
||||||
|
|
||||||
struct hub_command
|
|
||||||
{
|
|
||||||
const char* message;
|
|
||||||
char* prefix;
|
|
||||||
size_t prefix_len;
|
|
||||||
struct linked_list* args;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef int (*command_handler)(struct hub_info* hub, struct hub_user* user, struct hub_command*);
|
|
||||||
|
|
||||||
struct commands_handler
|
|
||||||
{
|
|
||||||
const char* prefix;
|
|
||||||
size_t length;
|
|
||||||
const char* args;
|
|
||||||
enum user_credentials cred;
|
|
||||||
command_handler handler;
|
|
||||||
const char* description;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct commands_handler command_handlers[];
|
|
||||||
|
|
||||||
static void command_destroy(struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
if (!cmd) return;
|
|
||||||
hub_free(cmd->prefix);
|
|
||||||
|
|
||||||
if (cmd->args)
|
|
||||||
{
|
|
||||||
list_clear(cmd->args, &hub_free);
|
|
||||||
list_destroy(cmd->args);
|
|
||||||
}
|
|
||||||
|
|
||||||
hub_free(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();
|
|
||||||
|
|
||||||
n = split_string(message, "\\s", cmd->args, 0);
|
|
||||||
if (n <= 0)
|
|
||||||
{
|
|
||||||
command_destroy(cmd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
prefix = list_get_first(cmd->args);
|
|
||||||
if (prefix && prefix[0] && prefix[1])
|
|
||||||
{
|
|
||||||
cmd->prefix = hub_strdup(&prefix[1]);
|
|
||||||
cmd->prefix_len = strlen(cmd->prefix);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
command_destroy(cmd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
list_remove(cmd->args, prefix);
|
|
||||||
hub_free(prefix);
|
|
||||||
return cmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void send_message(struct hub_info* hub, struct hub_user* user, const char* message)
|
|
||||||
{
|
|
||||||
char* buffer = adc_msg_escape(message);
|
|
||||||
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
|
||||||
adc_msg_add_argument(command, buffer);
|
|
||||||
route_to_user(hub, user, command);
|
|
||||||
adc_msg_free(command);
|
|
||||||
hub_free(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_access_denied(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
char temp[128];
|
|
||||||
snprintf(temp, 128, "*** %s: Access denied.", cmd->prefix);
|
|
||||||
send_message(hub, user, temp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_not_found(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
char temp[128];
|
|
||||||
snprintf(temp, 128, "*** %s: Command not found", cmd->prefix);
|
|
||||||
send_message(hub, user, temp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_status_user_not_found(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd, const char* nick)
|
|
||||||
{
|
|
||||||
char temp[128];
|
|
||||||
snprintf(temp, 128, "*** %s: No user \"%s\"", cmd->prefix, nick);
|
|
||||||
send_message(hub, user, temp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* command_get_syntax(struct commands_handler* handler)
|
|
||||||
{
|
|
||||||
static char args[128];
|
|
||||||
size_t n = 0;
|
|
||||||
args[0] = 0;
|
|
||||||
if (handler->args)
|
|
||||||
{
|
|
||||||
for (n = 0; n < strlen(handler->args); n++)
|
|
||||||
{
|
|
||||||
if (n > 0) strcat(args, " ");
|
|
||||||
switch (handler->args[n])
|
|
||||||
{
|
|
||||||
case 'n': strcat(args, "<nick>"); break;
|
|
||||||
case 'c': strcat(args, "<cid>"); break;
|
|
||||||
case 'a': strcat(args, "<addr>"); break;
|
|
||||||
case 'm': strcat(args, "<message>"); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_arg_mismatch(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd, struct commands_handler* handler)
|
|
||||||
{
|
|
||||||
char temp[256];
|
|
||||||
const char* args = command_get_syntax(handler);
|
|
||||||
if (args) snprintf(temp, 256, "*** %s: Use: !%s %s", cmd->prefix, cmd->prefix, args);
|
|
||||||
else snprintf(temp, 256, "*** %s: Use: !%s", cmd->prefix, cmd->prefix);
|
|
||||||
send_message(hub, user, temp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_status(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd, const char* message)
|
|
||||||
{
|
|
||||||
char temp[1024];
|
|
||||||
snprintf(temp, 1024, "*** %s: %s", cmd->prefix, message);
|
|
||||||
send_message(hub, user, temp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_stats(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
char temp[128];
|
|
||||||
snprintf(temp, 128, PRINTF_SIZE_T " users, peak: " PRINTF_SIZE_T ". Network (up/down): %d/%d KB/s, peak: %d/%d KB/s",
|
|
||||||
hub->users->count,
|
|
||||||
hub->users->count_peak,
|
|
||||||
(int) hub->stats.net_tx / 1024,
|
|
||||||
(int) hub->stats.net_rx / 1024,
|
|
||||||
(int) hub->stats.net_tx_peak / 1024,
|
|
||||||
(int) hub->stats.net_rx_peak / 1024);
|
|
||||||
return command_status(hub, user, cmd, temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_help(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
size_t n;
|
|
||||||
char msg[MAX_HELP_MSG];
|
|
||||||
msg[0] = 0;
|
|
||||||
strcat(msg, "Available commands:\n");
|
|
||||||
|
|
||||||
for (n = 0; command_handlers[n].prefix; n++)
|
|
||||||
{
|
|
||||||
if (command_handlers[n].cred <= user->credentials)
|
|
||||||
{
|
|
||||||
strcat(msg, "!");
|
|
||||||
strcat(msg, command_handlers[n].prefix);
|
|
||||||
strcat(msg, " - ");
|
|
||||||
strcat(msg, command_handlers[n].description);
|
|
||||||
strcat(msg, "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return command_status(hub, user, cmd, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_uptime(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
char tmp[128];
|
|
||||||
size_t d;
|
|
||||||
size_t h;
|
|
||||||
size_t m;
|
|
||||||
size_t D = (size_t) difftime(time(0), hub->tm_started);
|
|
||||||
|
|
||||||
d = D / (24 * 3600);
|
|
||||||
D = D % (24 * 3600);
|
|
||||||
h = D / 3600;
|
|
||||||
D = D % 3600;
|
|
||||||
m = D / 60;
|
|
||||||
|
|
||||||
tmp[0] = 0;
|
|
||||||
if (d)
|
|
||||||
{
|
|
||||||
strcat(tmp, uhub_itoa((int) d));
|
|
||||||
strcat(tmp, " day");
|
|
||||||
if (d != 1) strcat(tmp, "s");
|
|
||||||
strcat(tmp, ", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h < 10) strcat(tmp, "0");
|
|
||||||
strcat(tmp, uhub_itoa((int) h));
|
|
||||||
strcat(tmp, ":");
|
|
||||||
if (m < 10) strcat(tmp, "0");
|
|
||||||
strcat(tmp, uhub_itoa((int) m));
|
|
||||||
|
|
||||||
return command_status(hub, user, cmd, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
target = uman_get_user_by_nick(hub, nick);
|
|
||||||
|
|
||||||
if (!target)
|
|
||||||
return command_status_user_not_found(hub, user, cmd, nick);
|
|
||||||
|
|
||||||
if (target == user)
|
|
||||||
return command_status(hub, user, cmd, "Cannot kick yourself");
|
|
||||||
|
|
||||||
hub_disconnect_user(hub, target, quit_kicked);
|
|
||||||
return command_status(hub, user, cmd, nick);
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
target = uman_get_user_by_nick(hub, nick);
|
|
||||||
|
|
||||||
if (!target)
|
|
||||||
return command_status_user_not_found(hub, user, cmd, nick);
|
|
||||||
|
|
||||||
if (target == user)
|
|
||||||
return command_status(hub, user, cmd, "Cannot kick/ban yourself");
|
|
||||||
|
|
||||||
hub_disconnect_user(hub, target, quit_kicked);
|
|
||||||
acl_user_ban_nick(hub->acl, target->id.nick);
|
|
||||||
acl_user_ban_cid(hub->acl, target->id.cid);
|
|
||||||
|
|
||||||
return command_status(hub, user, cmd, nick);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_unban(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
return command_status(hub, user, cmd, "Not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_mute(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
char* nick = list_get_first(cmd->args);
|
|
||||||
struct hub_user* target;
|
|
||||||
if (!nick)
|
|
||||||
return -1; // FIXME: bad syntax.
|
|
||||||
|
|
||||||
target = uman_get_user_by_nick(hub, nick);
|
|
||||||
|
|
||||||
if (!target)
|
|
||||||
return command_status_user_not_found(hub, user, cmd, nick);
|
|
||||||
|
|
||||||
if (strlen(cmd->prefix) == 4)
|
|
||||||
{
|
|
||||||
user_flag_set(target, flag_muted);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
user_flag_unset(target, flag_muted);
|
|
||||||
}
|
|
||||||
return command_status(hub, user, cmd, nick);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_reload(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
hub->status = hub_status_restart;
|
|
||||||
return command_status(hub, user, cmd, "Reloading configuration...");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_shutdown(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
hub->status = hub_status_shutdown;
|
|
||||||
return command_status(hub, user, cmd, "Hub shutting down...");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_version(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
char tmp[128];
|
|
||||||
snprintf(tmp, 128, "Your address is \"%s\"", user_get_address(user));
|
|
||||||
return command_status(hub, user, cmd, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
struct hub_user* target;
|
|
||||||
|
|
||||||
if (!nick);
|
|
||||||
return -1; // FIXME: bad syntax/OOM
|
|
||||||
|
|
||||||
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));
|
|
||||||
return command_status(hub, user, cmd, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_whoip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
char* address = list_get_first(cmd->args);
|
|
||||||
struct ip_range range;
|
|
||||||
struct linked_list* users;
|
|
||||||
struct hub_user* u;
|
|
||||||
int ret = 0;
|
|
||||||
char tmp[128];
|
|
||||||
char* buffer;
|
|
||||||
|
|
||||||
if (!address)
|
|
||||||
return -1; // FIXME: bad syntax.
|
|
||||||
|
|
||||||
ret = ip_convert_address_to_range(address, &range);
|
|
||||||
if (!ret)
|
|
||||||
return command_status(hub, user, cmd, "Invalid IP address/range/mask");
|
|
||||||
|
|
||||||
users = (struct linked_list*) list_create();
|
|
||||||
if (!users)
|
|
||||||
return -1; // FIXME: OOM
|
|
||||||
|
|
||||||
ret = uman_get_user_by_addr(hub, users, &range);
|
|
||||||
|
|
||||||
if (!ret)
|
|
||||||
{
|
|
||||||
list_destroy(users);
|
|
||||||
return command_status(hub, user, cmd, "No users found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(tmp, 128, "*** %s: Found %d match%s:", cmd->prefix, ret, ((ret != 1) ? "es" : ""));
|
|
||||||
|
|
||||||
buffer = hub_malloc(((MAX_NICK_LEN + INET6_ADDRSTRLEN + 5) * ret) + strlen(tmp) + 3);
|
|
||||||
if (!buffer)
|
|
||||||
{
|
|
||||||
list_destroy(users);
|
|
||||||
return -1; // FIXME: OOM
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer[0] = 0;
|
|
||||||
strcat(buffer, tmp);
|
|
||||||
strcat(buffer, "\n");
|
|
||||||
|
|
||||||
u = (struct hub_user*) list_get_first(users);
|
|
||||||
while (u)
|
|
||||||
{
|
|
||||||
strcat(buffer, u->id.nick);
|
|
||||||
strcat(buffer, " (");
|
|
||||||
strcat(buffer, user_get_address(u));
|
|
||||||
strcat(buffer, ")\n");
|
|
||||||
u = (struct hub_user*) list_get_next(users);
|
|
||||||
}
|
|
||||||
strcat(buffer, "\n");
|
|
||||||
|
|
||||||
send_message(hub, user, buffer);
|
|
||||||
hub_free(buffer);
|
|
||||||
list_destroy(users);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_broadcast(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen((cmd->message + 12)) + 6);
|
|
||||||
adc_msg_add_argument(command, (cmd->message + 12));
|
|
||||||
route_to_all(hub, command);
|
|
||||||
adc_msg_free(command);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_history(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
char* buffer;
|
|
||||||
struct linked_list* messages = hub->chat_history;
|
|
||||||
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.");
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(tmp, 128, "*** %s: Found %d message%s:", cmd->prefix, ret, ((ret != 1) ? "s" : ""));
|
|
||||||
bufsize = strlen(tmp);
|
|
||||||
message = (char*) list_get_first(messages);
|
|
||||||
while (message)
|
|
||||||
{
|
|
||||||
bufsize += strlen(message);
|
|
||||||
message = (char*) list_get_next(messages);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = hub_malloc(bufsize+4);
|
|
||||||
if (!buffer)
|
|
||||||
{
|
|
||||||
return command_status(hub, user, cmd, "Not enough memory.");
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer[0] = 0;
|
|
||||||
strcat(buffer, tmp);
|
|
||||||
strcat(buffer, "\n");
|
|
||||||
|
|
||||||
message = (char*) list_get_first(messages);
|
|
||||||
while (message)
|
|
||||||
{
|
|
||||||
strcat(buffer, message);
|
|
||||||
message = (char*) list_get_next(messages);
|
|
||||||
}
|
|
||||||
strcat(buffer, "\n");
|
|
||||||
|
|
||||||
send_message(hub, user, buffer);
|
|
||||||
hub_free(buffer);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_log(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
struct linked_list* messages = hub->logout_info;
|
|
||||||
struct hub_logout_info* log;
|
|
||||||
char tmp[1024];
|
|
||||||
char* search = 0;
|
|
||||||
size_t search_len = 0;
|
|
||||||
size_t search_hits = 0;
|
|
||||||
|
|
||||||
if (!list_size(messages))
|
|
||||||
{
|
|
||||||
return command_status(hub, user, cmd, "No entries logged.");
|
|
||||||
}
|
|
||||||
|
|
||||||
search = list_get_first(cmd->args);
|
|
||||||
if (search)
|
|
||||||
{
|
|
||||||
search_len = strlen(search);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (search_len)
|
|
||||||
{
|
|
||||||
sprintf(tmp, "Logged entries: " PRINTF_SIZE_T ", searching for \"%s\"", list_size(messages), search);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf(tmp, "Logged entries: " PRINTF_SIZE_T, list_size(messages));
|
|
||||||
}
|
|
||||||
command_status(hub, user, cmd, tmp);
|
|
||||||
|
|
||||||
log = (struct hub_logout_info*) list_get_first(messages);
|
|
||||||
while (log)
|
|
||||||
{
|
|
||||||
const char* address = ip_convert_to_string(&log->addr);
|
|
||||||
int show = 0;
|
|
||||||
|
|
||||||
if (search_len)
|
|
||||||
{
|
|
||||||
if (memmem(log->cid, MAX_CID_LEN, search, search_len) || memmem(log->nick, MAX_NICK_LEN, search, search_len) || memmem(address, strlen(address), search, search_len))
|
|
||||||
{
|
|
||||||
search_hits++;
|
|
||||||
show = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
show = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (show)
|
|
||||||
{
|
|
||||||
sprintf(tmp, "* %s %s, %s [%s] - %s", get_timestamp(log->time), log->cid, log->nick, ip_convert_to_string(&log->addr), user_get_quit_reason_string(log->reason));
|
|
||||||
send_message(hub, user, tmp);
|
|
||||||
}
|
|
||||||
log = (struct hub_logout_info*) list_get_next(messages);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (search_len)
|
|
||||||
{
|
|
||||||
sprintf(tmp, PRINTF_SIZE_T " entries shown.", search_hits);
|
|
||||||
command_status(hub, user, cmd, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_rules(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
if (!hub_send_rules(hub, user))
|
|
||||||
return command_status(hub, user, cmd, "no rules defined.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_motd(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
if (!hub_send_motd(hub, user))
|
|
||||||
return command_status(hub, user, cmd, "no motd defined.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CRASH_DEBUG
|
|
||||||
static int command_crash(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
|
||||||
{
|
|
||||||
void (*crash)(void) = NULL;
|
|
||||||
crash();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int command_dipatcher(struct hub_info* hub, struct hub_user* user, const char* message)
|
|
||||||
{
|
|
||||||
size_t n = 0;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
/* Parse and validate the command */
|
|
||||||
struct hub_command* cmd = command_create(message);
|
|
||||||
if (!cmd) return 0;
|
|
||||||
|
|
||||||
for (n = 0; command_handlers[n].prefix; n++)
|
|
||||||
{
|
|
||||||
struct commands_handler* handler = &command_handlers[n];
|
|
||||||
if (cmd->prefix_len != handler->length)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!strncmp(cmd->prefix, handler->prefix, handler->length))
|
|
||||||
{
|
|
||||||
if (handler->cred <= user->credentials)
|
|
||||||
{
|
|
||||||
if (!handler->args || (handler->args && list_size(cmd->args) >= strlen(handler->args)))
|
|
||||||
{
|
|
||||||
rc = handler->handler(hub, user, cmd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rc = command_arg_mismatch(hub, user, cmd, handler);
|
|
||||||
}
|
|
||||||
command_destroy(cmd);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rc = command_access_denied(hub, user, cmd);
|
|
||||||
command_destroy(cmd);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
command_not_found(hub, user, cmd);
|
|
||||||
command_destroy(cmd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct commands_handler command_handlers[] = {
|
|
||||||
{ "ban", 3, "n", cred_operator, command_ban, "Ban a user" },
|
|
||||||
{ "broadcast", 9, "m", cred_operator, command_broadcast,"Send a message to all users" },
|
|
||||||
#ifdef CRASH_DEBUG
|
|
||||||
{ "crash", 5, 0, cred_admin, command_crash, "Crash the hub (DEBUG)." },
|
|
||||||
#endif
|
|
||||||
{ "getip", 5, "n", cred_operator, command_getip, "Show IP address for a user" },
|
|
||||||
{ "help", 4, 0, cred_guest, command_help, "Show this help message." },
|
|
||||||
{ "history", 7, 0, cred_guest, command_history, "Show the last chat messages." },
|
|
||||||
{ "kick", 4, "n", cred_operator, command_kick, "Kick a user" },
|
|
||||||
{ "log", 3, 0, cred_operator, command_log, "Display log" },
|
|
||||||
{ "motd", 4, 0, cred_guest, command_motd, "Show the message of the day" },
|
|
||||||
{ "mute", 4, "n", cred_operator, command_mute, "Mute user" },
|
|
||||||
{ "myip", 4, 0, cred_guest, command_myip, "Show your own IP." },
|
|
||||||
{ "reload", 6, 0, cred_admin, command_reload, "Reload configuration files." },
|
|
||||||
{ "rules", 5, 0, cred_guest, command_rules, "Show the hub rules" },
|
|
||||||
{ "shutdown", 8, 0, cred_admin, command_shutdown, "Shutdown hub." },
|
|
||||||
{ "stats", 5, 0, cred_super, command_stats, "Show hub statistics." },
|
|
||||||
{ "unban", 5, "n", cred_operator, command_unban, "Lift ban on a user" },
|
|
||||||
{ "unmute", 6, "n", cred_operator, command_mute, "Unmute user" },
|
|
||||||
{ "uptime", 6, 0, cred_guest, command_uptime, "Display hub uptime info." },
|
|
||||||
{ "version", 7, 0, cred_guest, command_version, "Show hub version info." },
|
|
||||||
{ "whoip", 5, "a", cred_operator, command_whoip, "Show users matching IP range" },
|
|
||||||
{ 0, 0, 0, cred_none, command_help, "" }
|
|
||||||
};
|
|
||||||
|
|
||||||
1214
src/core/hub.c
1214
src/core/hub.c
File diff suppressed because it is too large
Load Diff
@@ -1,114 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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"
|
|
||||||
|
|
||||||
static void log_user_login(struct hub_user* u)
|
|
||||||
{
|
|
||||||
const char* cred = get_user_credential_string(u->credentials);
|
|
||||||
const char* addr = user_get_address(u);
|
|
||||||
LOG_USER("LoginOK %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, cred, u->user_agent);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void log_user_login_error(struct 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("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);
|
|
||||||
LOG_USER("Logout %s/%s %s \"%s\" (%s)", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void log_user_nick_change(struct hub_user* u, const char* nick)
|
|
||||||
{
|
|
||||||
const char* addr = user_get_address(u);
|
|
||||||
LOG_USER("NickChange %s/%s %s \"%s\" -> \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, nick);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Send MOTD, do logging etc */
|
|
||||||
void on_login_success(struct hub_info* hub, struct hub_user* u)
|
|
||||||
{
|
|
||||||
/* Send user list of all existing users */
|
|
||||||
if (!uman_send_user_list(hub, u))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Mark as being in the normal state, and add user to the user list */
|
|
||||||
user_set_state(u, state_normal);
|
|
||||||
uman_add(hub, u);
|
|
||||||
|
|
||||||
/* Print log message */
|
|
||||||
log_user_login(u);
|
|
||||||
|
|
||||||
/* Announce new user to all connected users */
|
|
||||||
if (user_is_logged_in(u))
|
|
||||||
route_info_message(hub, u);
|
|
||||||
|
|
||||||
/* Send message of the day (if any) */
|
|
||||||
if (user_is_logged_in(u)) /* Previous send() can fail! */
|
|
||||||
hub_send_motd(hub, u);
|
|
||||||
|
|
||||||
/* Send message of the day (if any) */
|
|
||||||
if (user_is_logged_in(u)) /* Previous send() can fail! */
|
|
||||||
hub_send_rules(hub, u);
|
|
||||||
|
|
||||||
/* reset timeout */
|
|
||||||
net_con_clear_timeout(u->connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg)
|
|
||||||
{
|
|
||||||
log_user_login_error(u, msg);
|
|
||||||
hub_send_status(hub, u, msg, status_level_fatal);
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
log_user_nick_change(u, nick);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_logout_user(struct hub_info* hub, struct hub_user* user)
|
|
||||||
{
|
|
||||||
const char* reason = user_get_quit_reason_string(user->quit_reason);
|
|
||||||
log_user_logout(user, reason);
|
|
||||||
hub_logout_log(hub, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
173
src/core/hubio.c
173
src/core/hubio.c
@@ -1,173 +0,0 @@
|
|||||||
/*
|
|
||||||
* uhub - A tiny ADC p2p connection hub
|
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "uhub.h"
|
|
||||||
#include "hubio.h"
|
|
||||||
|
|
||||||
#ifdef DEBUG_SENDQ
|
|
||||||
static void debug_msg(const char* prefix, struct adc_message* msg)
|
|
||||||
{
|
|
||||||
size_t n;
|
|
||||||
char* buf = strdup(msg->cache);
|
|
||||||
for (n = 0; n < msg->length; n++)
|
|
||||||
{
|
|
||||||
if (buf[n] == '\r' || buf[n] == '\n')
|
|
||||||
buf[n] = '_';
|
|
||||||
}
|
|
||||||
LOG_TRACE("%s: [%s] (%d bytes)", prefix, buf, (int) msg->length);
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct hub_recvq* hub_recvq_create()
|
|
||||||
{
|
|
||||||
struct hub_recvq* q = hub_malloc_zero(sizeof(struct hub_recvq));
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
|
|
||||||
void hub_recvq_destroy(struct hub_recvq* q)
|
|
||||||
{
|
|
||||||
if (q)
|
|
||||||
{
|
|
||||||
hub_free(q->buf);
|
|
||||||
hub_free(q);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t hub_recvq_get(struct hub_recvq* q, void* buf, size_t bufsize)
|
|
||||||
{
|
|
||||||
assert(bufsize >= q->size);
|
|
||||||
if (q->size)
|
|
||||||
{
|
|
||||||
size_t n = q->size;
|
|
||||||
memcpy(buf, q->buf, n);
|
|
||||||
hub_free(q->buf);
|
|
||||||
q->buf = 0;
|
|
||||||
q->size = 0;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t hub_recvq_set(struct hub_recvq* q, void* buf, size_t bufsize)
|
|
||||||
{
|
|
||||||
if (q->buf)
|
|
||||||
{
|
|
||||||
hub_free(q->buf);
|
|
||||||
q->buf = 0;
|
|
||||||
q->size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bufsize)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
q->buf = hub_malloc(bufsize);
|
|
||||||
if (!q->buf)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
q->size = bufsize;
|
|
||||||
memcpy(q->buf, buf, bufsize);
|
|
||||||
return bufsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct hub_sendq* hub_sendq_create()
|
|
||||||
{
|
|
||||||
struct hub_sendq* q = hub_malloc_zero(sizeof(struct hub_sendq));
|
|
||||||
if (!q)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
q->queue = list_create();
|
|
||||||
if (!q->queue)
|
|
||||||
{
|
|
||||||
hub_free(q);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clear_send_queue_callback(void* ptr)
|
|
||||||
{
|
|
||||||
adc_msg_free((struct adc_message*) ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void hub_sendq_destroy(struct hub_sendq* q)
|
|
||||||
{
|
|
||||||
if (q)
|
|
||||||
{
|
|
||||||
list_clear(q->queue, &clear_send_queue_callback);
|
|
||||||
list_destroy(q->queue);
|
|
||||||
hub_free(q);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void hub_sendq_add(struct hub_sendq* q, struct adc_message* msg_)
|
|
||||||
{
|
|
||||||
struct adc_message* msg = adc_msg_incref(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void hub_sendq_remove(struct hub_sendq* q, struct adc_message* msg)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG_SENDQ
|
|
||||||
debug_msg("hub_sendq_remove", msg);
|
|
||||||
#endif
|
|
||||||
list_remove(q->queue, msg);
|
|
||||||
q->size -= msg->length;
|
|
||||||
adc_msg_free(msg);
|
|
||||||
q->offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
assert(msg->cache && *msg->cache);
|
|
||||||
ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
|
|
||||||
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
q->offset += ret;
|
|
||||||
if (msg->length - q->offset > 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
hub_sendq_remove(q, msg);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int hub_sendq_is_empty(struct hub_sendq* q)
|
|
||||||
{
|
|
||||||
return (q->size - q->offset) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t hub_sendq_get_bytes(struct hub_sendq* q)
|
|
||||||
{
|
|
||||||
return q->size - q->offset;
|
|
||||||
}
|
|
||||||
106
src/core/hubio.h
106
src/core/hubio.h
@@ -1,106 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_HUB_IO_H
|
|
||||||
#define HAVE_UHUB_HUB_IO_H
|
|
||||||
|
|
||||||
struct adc_message;
|
|
||||||
struct linked_list;
|
|
||||||
typedef int (*hub_recvq_write)(void* desc, const void* buf, size_t len);
|
|
||||||
typedef int (*hub_recvq_read)(void* desc, void* buf, size_t len);
|
|
||||||
|
|
||||||
struct hub_sendq
|
|
||||||
{
|
|
||||||
size_t size; /** Size of send queue (in bytes, not messages) */
|
|
||||||
size_t offset; /** Queue byte offset in the first message. Should be 0 unless a partial write. */
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
size_t last_send; /** When using SSL, one have to send the exact same buffer and length if a write cannot complete. */
|
|
||||||
#endif
|
|
||||||
struct linked_list* queue; /** List of queued messages */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct hub_recvq
|
|
||||||
{
|
|
||||||
char* buf;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a send queue
|
|
||||||
*/
|
|
||||||
extern struct hub_sendq* hub_sendq_create();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroy a send queue, and delete any queued messages.
|
|
||||||
*/
|
|
||||||
extern void hub_sendq_destroy(struct hub_sendq*);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a message to the send queue.
|
|
||||||
*/
|
|
||||||
extern void hub_sendq_add(struct hub_sendq*, struct adc_message* msg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process the send queue, and send as many messages as possible.
|
|
||||||
* @returns -1 on error, 0 if unable to send more, 1 if more can be sent.
|
|
||||||
*/
|
|
||||||
extern int hub_sendq_send(struct hub_sendq*, struct hub_user*);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns 1 if send queue is empty, 0 otherwise.
|
|
||||||
*/
|
|
||||||
extern int hub_sendq_is_empty(struct hub_sendq*);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns the number of bytes remaining to be sent in the queue.
|
|
||||||
*/
|
|
||||||
extern size_t hub_sendq_get_bytes(struct hub_sendq*);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a receive queue.
|
|
||||||
*/
|
|
||||||
extern struct hub_recvq* hub_recvq_create();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroy a receive queue.
|
|
||||||
*/
|
|
||||||
extern void hub_recvq_destroy(struct hub_recvq*);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the buffer, copies it into buf and deallocates it.
|
|
||||||
* NOTE: bufsize *MUST* be larger than the buffer, otherwise it asserts.
|
|
||||||
* @return the number of bytes copied into buf.
|
|
||||||
*/
|
|
||||||
extern size_t hub_recvq_get(struct hub_recvq*, void* buf, size_t bufsize);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the buffer
|
|
||||||
*/
|
|
||||||
extern size_t hub_recvq_set(struct hub_recvq*, void* buf, size_t bufsize);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return 1 if size is zero, 0 otherwise.
|
|
||||||
*/
|
|
||||||
extern int hub_recvq_is_empty(struct hub_recvq* buf);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_HUB_IO_H */
|
|
||||||
@@ -1,219 +0,0 @@
|
|||||||
/*
|
|
||||||
* uhub - A tiny ADC p2p connection hub
|
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <uhub.h>
|
|
||||||
#include "hubio.h"
|
|
||||||
#include "probe.h"
|
|
||||||
|
|
||||||
/* FIXME: This should not be needed! */
|
|
||||||
extern struct hub_info* g_hub;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (size < 0)
|
|
||||||
{
|
|
||||||
if (size == -1)
|
|
||||||
return quit_disconnected;
|
|
||||||
else
|
|
||||||
return quit_socket_error;
|
|
||||||
}
|
|
||||||
else if (size == 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char* lastPos = 0;
|
|
||||||
char* start = buf;
|
|
||||||
char* pos = 0;
|
|
||||||
size_t remaining = buf_size;
|
|
||||||
|
|
||||||
while ((pos = memchr(start, '\n', remaining)))
|
|
||||||
{
|
|
||||||
lastPos = pos;
|
|
||||||
pos[0] = '\0';
|
|
||||||
|
|
||||||
#ifdef DEBUG_SENDQ
|
|
||||||
LOG_DUMP("PROC: \"%s\" (%d)\n", start, (int) (pos - start));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (user_flag_get(user, flag_maxbuf))
|
|
||||||
{
|
|
||||||
user_flag_unset(user, flag_maxbuf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (((pos - start) > 0) && g_hub->config->max_recv_buffer > (pos - start))
|
|
||||||
{
|
|
||||||
if (hub_handle_message(g_hub, user, start, (pos - start)) == -1)
|
|
||||||
{
|
|
||||||
return quit_protocol_error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pos[0] = '\n'; /* FIXME: not needed */
|
|
||||||
pos ++;
|
|
||||||
remaining -= (pos - start);
|
|
||||||
start = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastPos || remaining)
|
|
||||||
{
|
|
||||||
if (remaining < g_hub->config->max_recv_buffer)
|
|
||||||
{
|
|
||||||
hub_recvq_set(q, lastPos ? lastPos : buf, remaining);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hub_recvq_set(q, 0, 0);
|
|
||||||
user_flag_set(user, flag_maxbuf);
|
|
||||||
LOG_WARN("Received message past max_recv_buffer, dropping message.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hub_recvq_set(q, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int handle_net_write(struct hub_user* user)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
while (hub_sendq_get_bytes(user->send_queue))
|
|
||||||
{
|
|
||||||
ret = hub_sendq_send(user->send_queue, user);
|
|
||||||
if (ret <= 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
return quit_socket_error;
|
|
||||||
|
|
||||||
if (hub_sendq_get_bytes(user->send_queue))
|
|
||||||
{
|
|
||||||
user_net_io_want_write(user);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
user_net_io_want_read(user);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_event(struct net_connection* con, int event, void *arg)
|
|
||||||
{
|
|
||||||
struct hub_user* user = (struct hub_user*) arg;
|
|
||||||
int flag_close = 0;
|
|
||||||
|
|
||||||
#ifdef DEBUG_SENDQ
|
|
||||||
LOG_TRACE("net_event() : fd=%d, ev=%d, arg=%p", con->sd, (int) event, arg);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (event == NET_EVENT_TIMEOUT)
|
|
||||||
{
|
|
||||||
if (user_is_connecting(user))
|
|
||||||
{
|
|
||||||
hub_disconnect_user(g_hub, user, quit_timeout);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event & NET_EVENT_READ)
|
|
||||||
{
|
|
||||||
flag_close = handle_net_read(user);
|
|
||||||
if (flag_close)
|
|
||||||
{
|
|
||||||
hub_disconnect_user(g_hub, user, flag_close);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event & NET_EVENT_WRITE)
|
|
||||||
{
|
|
||||||
flag_close = handle_net_write(user);
|
|
||||||
if (flag_close)
|
|
||||||
{
|
|
||||||
hub_disconnect_user(g_hub, user, flag_close);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_on_accept(struct net_connection* con, int event, void *arg)
|
|
||||||
{
|
|
||||||
struct hub_info* hub = (struct hub_info*) arg;
|
|
||||||
struct hub_probe* probe = 0;
|
|
||||||
struct ip_addr_encap ipaddr;
|
|
||||||
const char* addr;
|
|
||||||
int server_fd = net_con_get_sd(con);
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
int fd = net_accept(server_fd, &ipaddr);
|
|
||||||
if (fd == -1)
|
|
||||||
{
|
|
||||||
if (net_error() == EWOULDBLOCK)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR("Accept error: %d %s", net_error(), strerror(net_error()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addr = ip_convert_to_string(&ipaddr);
|
|
||||||
|
|
||||||
/* FIXME: Should have a plugin log this */
|
|
||||||
LOG_TRACE("Got connection from %s", addr);
|
|
||||||
|
|
||||||
/* FIXME: A plugin should perform this check: is IP banned? */
|
|
||||||
if (acl_is_ip_banned(hub->acl, addr))
|
|
||||||
{
|
|
||||||
LOG_INFO("Denied [%s] (IP banned)", addr);
|
|
||||||
net_close(fd);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
probe = probe_create(hub, fd, &ipaddr);
|
|
||||||
if (!probe)
|
|
||||||
{
|
|
||||||
LOG_ERROR("Unable to create probe after socket accepted. Out of memory?");
|
|
||||||
net_close(fd);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
126
src/core/probe.c
126
src/core/probe.c
@@ -1,126 +0,0 @@
|
|||||||
/*
|
|
||||||
* uhub - A tiny ADC p2p connection hub
|
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "uhub.h"
|
|
||||||
#include "probe.h"
|
|
||||||
|
|
||||||
#define PROBE_RECV_SIZE 12
|
|
||||||
static char probe_recvbuf[PROBE_RECV_SIZE];
|
|
||||||
|
|
||||||
static void probe_net_event(struct net_connection* con, int events, void *arg)
|
|
||||||
{
|
|
||||||
struct hub_probe* probe = (struct hub_probe*) net_con_get_ptr(con);
|
|
||||||
if (events == NET_EVENT_TIMEOUT)
|
|
||||||
{
|
|
||||||
probe_destroy(probe);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (events & NET_EVENT_READ)
|
|
||||||
{
|
|
||||||
int bytes = net_con_peek(con, probe_recvbuf, PROBE_RECV_SIZE);
|
|
||||||
if (bytes < 0)
|
|
||||||
{
|
|
||||||
probe_destroy(probe);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bytes >= 4)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
probe_destroy(probe);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
if (bytes >= 11 &&
|
|
||||||
probe_recvbuf[0] == 22 &&
|
|
||||||
probe_recvbuf[1] == 3 && /* protocol major version */
|
|
||||||
probe_recvbuf[5] == 1 && /* message type */
|
|
||||||
probe_recvbuf[9] == probe_recvbuf[1] &&
|
|
||||||
probe_recvbuf[10] == probe_recvbuf[2])
|
|
||||||
{
|
|
||||||
if (probe->hub->config->tls_enable)
|
|
||||||
{
|
|
||||||
LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
|
|
||||||
if (user_create(probe->hub, probe->connection, &probe->addr))
|
|
||||||
{
|
|
||||||
probe->connection = 0;
|
|
||||||
}
|
|
||||||
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_TRACE("Probed TLS %d.%d connection. TLS disabled in hub.", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
|
|
||||||
}
|
|
||||||
probe_destroy(probe);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
|
|
||||||
|
|
||||||
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
probe_destroy(probe);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct hub_probe* probe_create(struct hub_info* hub, int sd, struct ip_addr_encap* addr)
|
|
||||||
{
|
|
||||||
struct hub_probe* probe = (struct hub_probe*) hub_malloc_zero(sizeof(struct hub_probe));
|
|
||||||
|
|
||||||
if (probe == NULL)
|
|
||||||
return NULL; /* OOM */
|
|
||||||
|
|
||||||
probe->hub = hub;
|
|
||||||
probe->connection = net_con_create();
|
|
||||||
net_con_initialize(probe->connection, sd, probe_net_event, probe, NET_EVENT_READ);
|
|
||||||
net_con_set_timeout(probe->connection, TIMEOUT_CONNECTED);
|
|
||||||
|
|
||||||
memcpy(&probe->addr, addr, sizeof(struct ip_addr_encap));
|
|
||||||
return probe;
|
|
||||||
}
|
|
||||||
|
|
||||||
void probe_destroy(struct hub_probe* probe)
|
|
||||||
{
|
|
||||||
if (probe->connection)
|
|
||||||
{
|
|
||||||
net_con_close(probe->connection);
|
|
||||||
probe->connection = 0;
|
|
||||||
}
|
|
||||||
hub_free(probe);
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_PROBE_H
|
|
||||||
#define HAVE_UHUB_PROBE_H
|
|
||||||
|
|
||||||
#include "uhub.h"
|
|
||||||
|
|
||||||
struct hub_probe
|
|
||||||
{
|
|
||||||
struct hub_info* hub; /** The hub instance this probe belong to */
|
|
||||||
struct net_connection* connection; /** Connection data */
|
|
||||||
struct ip_addr_encap addr; /** IP address */
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct hub_probe* probe_create(struct hub_info* hub, int sd, struct ip_addr_encap* addr);
|
|
||||||
extern void probe_destroy(struct hub_probe* probe);
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_PROBE_H */
|
|
||||||
230
src/core/route.c
230
src/core/route.c
@@ -1,230 +0,0 @@
|
|||||||
/*
|
|
||||||
* uhub - A tiny ADC p2p connection hub
|
|
||||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "uhub.h"
|
|
||||||
|
|
||||||
int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message* msg)
|
|
||||||
{
|
|
||||||
struct hub_user* target = NULL;
|
|
||||||
|
|
||||||
switch (msg->cache[0])
|
|
||||||
{
|
|
||||||
case 'B': /* Broadcast to all logged in clients */
|
|
||||||
route_to_all(hub, msg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'D':
|
|
||||||
target = uman_get_user_by_sid(hub, msg->target);
|
|
||||||
if (target)
|
|
||||||
{
|
|
||||||
route_to_user(hub, target, msg);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'E':
|
|
||||||
target = uman_get_user_by_sid(hub, msg->target);
|
|
||||||
if (target)
|
|
||||||
{
|
|
||||||
route_to_user(hub, target, msg);
|
|
||||||
route_to_user(hub, u, msg);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'F':
|
|
||||||
route_to_subscribers(hub, msg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
/* Ignore the message */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline size_t get_max_send_queue(struct hub_info* hub)
|
|
||||||
{
|
|
||||||
/* TODO: More dynamic send queue limit, for instance:
|
|
||||||
* return MAX(hub->config->max_send_buffer, (hub->config->max_recv_buffer * hub_get_user_count(hub)));
|
|
||||||
*/
|
|
||||||
return hub->config->max_send_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline size_t get_max_send_queue_soft(struct hub_info* hub)
|
|
||||||
{
|
|
||||||
return hub->config->max_send_buffer_soft;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @return 1 if send queue is OK.
|
|
||||||
* -1 if send queue is overflowed
|
|
||||||
* 0 if soft send queue is overflowed (not implemented at the moment)
|
|
||||||
*/
|
|
||||||
static inline int check_send_queue(struct hub_info* hub, struct hub_user* user, struct adc_message* msg)
|
|
||||||
{
|
|
||||||
if (user_flag_get(user, flag_user_list))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if ((user->send_queue->size + msg->length) > get_max_send_queue(hub))
|
|
||||||
{
|
|
||||||
LOG_WARN("send queue overflowed, message discarded.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user->send_queue->size > get_max_send_queue_soft(hub))
|
|
||||||
{
|
|
||||||
LOG_WARN("send queue soft overflowed.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_message* msg)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG_SENDQ
|
|
||||||
char* data = strndup(msg->cache, msg->length-1);
|
|
||||||
LOG_PROTO("send %s: \"%s\"", sid_to_string(user->id.sid), data);
|
|
||||||
free(data);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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 */
|
|
||||||
hub_sendq_add(user->send_queue, msg);
|
|
||||||
handle_net_write(user);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (check_send_queue(hub, user, msg) >= 0)
|
|
||||||
{
|
|
||||||
hub_sendq_add(user->send_queue, msg);
|
|
||||||
if (!user_flag_get(user, flag_pipeline))
|
|
||||||
user_net_io_want_write(user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int route_flush_pipeline(struct hub_info* hub, struct hub_user* u)
|
|
||||||
{
|
|
||||||
if (hub_sendq_is_empty(u->send_queue))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
handle_net_write(u);
|
|
||||||
user_flag_unset(u, flag_pipeline);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int route_to_all(struct hub_info* hub, struct adc_message* command) /* iterate users */
|
|
||||||
{
|
|
||||||
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
|
|
||||||
while (user)
|
|
||||||
{
|
|
||||||
route_to_user(hub, user, command);
|
|
||||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int route_to_subscribers(struct hub_info* hub, struct adc_message* command) /* iterate users */
|
|
||||||
{
|
|
||||||
int do_send;
|
|
||||||
char* tmp;
|
|
||||||
|
|
||||||
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
|
|
||||||
while (user)
|
|
||||||
{
|
|
||||||
if (user->feature_cast)
|
|
||||||
{
|
|
||||||
do_send = 1;
|
|
||||||
|
|
||||||
tmp = list_get_first(command->feature_cast_include);
|
|
||||||
while (tmp)
|
|
||||||
{
|
|
||||||
if (!user_have_feature_cast_support(user, tmp))
|
|
||||||
{
|
|
||||||
do_send = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tmp = list_get_next(command->feature_cast_include);;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!do_send) {
|
|
||||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp = list_get_first(command->feature_cast_exclude);
|
|
||||||
while (tmp)
|
|
||||||
{
|
|
||||||
if (user_have_feature_cast_support(user, tmp))
|
|
||||||
{
|
|
||||||
do_send = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tmp = list_get_next(command->feature_cast_exclude);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (do_send)
|
|
||||||
{
|
|
||||||
route_to_user(hub, user, command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int route_info_message(struct hub_info* hub, struct hub_user* u)
|
|
||||||
{
|
|
||||||
if (!user_is_nat_override(u))
|
|
||||||
{
|
|
||||||
return route_to_all(hub, u->info);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
struct adc_message* cmd = adc_msg_copy(u->info);
|
|
||||||
const char* address = user_get_address(u);
|
|
||||||
struct hub_user* user = 0;
|
|
||||||
|
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
|
|
||||||
adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR, address);
|
|
||||||
|
|
||||||
user = (struct hub_user*) list_get_first(hub->users->list);
|
|
||||||
while (user)
|
|
||||||
{
|
|
||||||
if (user_is_nat_override(user))
|
|
||||||
route_to_user(hub, user, cmd);
|
|
||||||
else
|
|
||||||
route_to_user(hub, user, u->info);
|
|
||||||
|
|
||||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
|
||||||
}
|
|
||||||
adc_msg_free(cmd);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
356
src/core/user.c
356
src/core/user.c
@@ -1,356 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 DEBUG_SENDQ
|
|
||||||
static const char* user_log_str(struct hub_user* user)
|
|
||||||
{
|
|
||||||
static char buf[128];
|
|
||||||
if (user)
|
|
||||||
{
|
|
||||||
snprintf(buf, 128, "user={ %p, \"%s\", %s/%s}", user, user->id.nick, sid_to_string(user->id.sid), user->id.cid);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
snprintf(buf, 128, "user={ %p }", user);
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr)
|
|
||||||
{
|
|
||||||
struct hub_user* user = NULL;
|
|
||||||
|
|
||||||
LOG_TRACE("user_create(), hub=%p, con[sd=%d]", hub, net_con_get_sd(con));
|
|
||||||
|
|
||||||
user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
|
|
||||||
|
|
||||||
if (user == NULL)
|
|
||||||
return NULL; /* OOM */
|
|
||||||
|
|
||||||
user->send_queue = hub_sendq_create();
|
|
||||||
user->recv_queue = hub_recvq_create();
|
|
||||||
|
|
||||||
user->connection = con;
|
|
||||||
net_con_reinitialize(user->connection, net_event, user, NET_EVENT_READ);
|
|
||||||
|
|
||||||
memcpy(&user->id.addr, addr, sizeof(struct ip_addr_encap));
|
|
||||||
user_set_state(user, state_protocol);
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void user_destroy(struct hub_user* user)
|
|
||||||
{
|
|
||||||
LOG_TRACE("user_destroy(), user=%p", user);
|
|
||||||
|
|
||||||
hub_recvq_destroy(user->recv_queue);
|
|
||||||
hub_sendq_destroy(user->send_queue);
|
|
||||||
|
|
||||||
adc_msg_free(user->info);
|
|
||||||
user_clear_feature_cast_support(user);
|
|
||||||
hub_free(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
void user_set_state(struct hub_user* user, enum user_state state)
|
|
||||||
{
|
|
||||||
if ((user->state == state_cleanup && state != state_disconnected) || (user->state == state_disconnected))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
user->state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void user_set_info(struct hub_user* user, struct adc_message* cmd)
|
|
||||||
{
|
|
||||||
adc_msg_free(user->info);
|
|
||||||
if (cmd)
|
|
||||||
{
|
|
||||||
user->info = adc_msg_incref(cmd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
user->info = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void user_update_info(struct hub_user* u, struct adc_message* cmd)
|
|
||||||
{
|
|
||||||
char prefix[2];
|
|
||||||
char* argument;
|
|
||||||
size_t n = 0;
|
|
||||||
struct adc_message* cmd_new = adc_msg_copy(u->info);
|
|
||||||
if (!cmd_new)
|
|
||||||
{
|
|
||||||
/* FIXME: OOM! */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME: Optimization potential:
|
|
||||||
*
|
|
||||||
* remove parts of cmd that do not really change anything in cmd_new.
|
|
||||||
* this can save bandwidth if clients send multiple updates for information
|
|
||||||
* that does not really change anything.
|
|
||||||
*/
|
|
||||||
argument = adc_msg_get_argument(cmd, n++);
|
|
||||||
while (argument)
|
|
||||||
{
|
|
||||||
if (strlen(argument) >= 2)
|
|
||||||
{
|
|
||||||
prefix[0] = argument[0];
|
|
||||||
prefix[1] = argument[1];
|
|
||||||
adc_msg_replace_named_argument(cmd_new, prefix, argument+2);
|
|
||||||
}
|
|
||||||
|
|
||||||
hub_free(argument);
|
|
||||||
argument = adc_msg_get_argument(cmd, n++);
|
|
||||||
}
|
|
||||||
user_set_info(u, cmd_new);
|
|
||||||
adc_msg_free(cmd_new);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int convert_support_fourcc(int fourcc)
|
|
||||||
{
|
|
||||||
switch (fourcc)
|
|
||||||
{
|
|
||||||
case FOURCC('B','A','S','0'):
|
|
||||||
return feature_bas0;
|
|
||||||
|
|
||||||
case FOURCC('B','A','S','E'):
|
|
||||||
return feature_base;
|
|
||||||
|
|
||||||
case FOURCC('A','U','T','0'):
|
|
||||||
return feature_auto;
|
|
||||||
|
|
||||||
case FOURCC('U','C','M','0'):
|
|
||||||
case FOURCC('U','C','M','D'):
|
|
||||||
return feature_ucmd;
|
|
||||||
|
|
||||||
case FOURCC('Z','L','I','F'):
|
|
||||||
return feature_zlif;
|
|
||||||
|
|
||||||
case FOURCC('B','B','S','0'):
|
|
||||||
return feature_bbs;
|
|
||||||
|
|
||||||
case FOURCC('T','I','G','R'):
|
|
||||||
return feature_tiger;
|
|
||||||
|
|
||||||
case FOURCC('B','L','O','M'):
|
|
||||||
case FOURCC('B','L','O','0'):
|
|
||||||
return feature_bloom;
|
|
||||||
|
|
||||||
case FOURCC('P','I','N','G'):
|
|
||||||
return feature_ping;
|
|
||||||
|
|
||||||
case FOURCC('L','I','N','K'):
|
|
||||||
return feature_link;
|
|
||||||
|
|
||||||
case FOURCC('A','D','C','S'):
|
|
||||||
return feature_adcs;
|
|
||||||
|
|
||||||
default:
|
|
||||||
LOG_DEBUG("Unknown extension: %x", fourcc);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void user_support_add(struct hub_user* user, int fourcc)
|
|
||||||
{
|
|
||||||
int feature_mask = convert_support_fourcc(fourcc);
|
|
||||||
user->flags |= feature_mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
int user_flag_get(struct hub_user* user, enum user_flags flag)
|
|
||||||
{
|
|
||||||
return user->flags & flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
void user_flag_set(struct hub_user* user, enum user_flags flag)
|
|
||||||
{
|
|
||||||
user->flags |= flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
void user_flag_unset(struct hub_user* user, enum user_flags flag)
|
|
||||||
{
|
|
||||||
user->flags &= ~flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
void user_set_nat_override(struct hub_user* user)
|
|
||||||
{
|
|
||||||
user_flag_set(user, flag_nat);
|
|
||||||
}
|
|
||||||
|
|
||||||
int user_is_nat_override(struct hub_user* user)
|
|
||||||
{
|
|
||||||
return user_flag_get(user, flag_nat);
|
|
||||||
}
|
|
||||||
|
|
||||||
void user_support_remove(struct hub_user* user, int fourcc)
|
|
||||||
{
|
|
||||||
int feature_mask = convert_support_fourcc(fourcc);
|
|
||||||
user->flags &= ~feature_mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
int user_have_feature_cast_support(struct hub_user* user, char feature[4])
|
|
||||||
{
|
|
||||||
char* tmp = list_get_first(user->feature_cast);
|
|
||||||
while (tmp)
|
|
||||||
{
|
|
||||||
if (strncmp(tmp, feature, 4) == 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
tmp = list_get_next(user->feature_cast);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int user_set_feature_cast_support(struct hub_user* u, char feature[4])
|
|
||||||
{
|
|
||||||
if (!u->feature_cast)
|
|
||||||
{
|
|
||||||
u->feature_cast = list_create();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!u->feature_cast)
|
|
||||||
{
|
|
||||||
return 0; /* OOM! */
|
|
||||||
}
|
|
||||||
|
|
||||||
list_append(u->feature_cast, hub_strndup(feature, 4));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void user_clear_feature_cast_support(struct hub_user* u)
|
|
||||||
{
|
|
||||||
if (u->feature_cast)
|
|
||||||
{
|
|
||||||
list_clear(u->feature_cast, &hub_free);
|
|
||||||
list_destroy(u->feature_cast);
|
|
||||||
u->feature_cast = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int user_is_logged_in(struct hub_user* user)
|
|
||||||
{
|
|
||||||
if (user->state == state_normal)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int user_is_connecting(struct hub_user* user)
|
|
||||||
{
|
|
||||||
if (user->state == state_protocol || user->state == state_identify || user->state == state_verify)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int user_is_protocol_negotiating(struct hub_user* user)
|
|
||||||
{
|
|
||||||
if (user->state == state_protocol)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int user_is_disconnecting(struct hub_user* user)
|
|
||||||
{
|
|
||||||
if (user->state == state_cleanup || user->state == state_disconnected)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int user_is_protected(struct hub_user* user)
|
|
||||||
{
|
|
||||||
switch (user->credentials)
|
|
||||||
{
|
|
||||||
case cred_bot:
|
|
||||||
case cred_operator:
|
|
||||||
case cred_super:
|
|
||||||
case cred_admin:
|
|
||||||
case cred_link:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns 1 if a user is registered.
|
|
||||||
* Only registered users will be let in if the hub is configured for registered
|
|
||||||
* users only.
|
|
||||||
*/
|
|
||||||
int user_is_registered(struct hub_user* user)
|
|
||||||
{
|
|
||||||
switch (user->credentials)
|
|
||||||
{
|
|
||||||
case cred_bot:
|
|
||||||
case cred_user:
|
|
||||||
case cred_operator:
|
|
||||||
case cred_super:
|
|
||||||
case cred_admin:
|
|
||||||
case cred_link:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void user_net_io_want_write(struct hub_user* user)
|
|
||||||
{
|
|
||||||
net_con_update(user->connection, NET_EVENT_READ | NET_EVENT_WRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void user_net_io_want_read(struct hub_user* user)
|
|
||||||
{
|
|
||||||
net_con_update(user->connection, NET_EVENT_READ);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* user_get_quit_reason_string(enum user_quit_reason reason)
|
|
||||||
{
|
|
||||||
switch (reason)
|
|
||||||
{
|
|
||||||
case quit_unknown: return "unknown"; break;
|
|
||||||
case quit_disconnected: return "disconnected"; break;
|
|
||||||
case quit_kicked: return "kicked"; break;
|
|
||||||
case quit_banned: return "banned"; break;
|
|
||||||
case quit_timeout: return "timeout"; break;
|
|
||||||
case quit_send_queue: return "send queue"; break;
|
|
||||||
case quit_memory_error: return "out of memory"; break;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "unknown";
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* user_get_address(struct hub_user* user)
|
|
||||||
{
|
|
||||||
return ip_convert_to_string(&user->id.addr);
|
|
||||||
}
|
|
||||||
@@ -28,14 +28,10 @@
|
|||||||
/* Send a broadcast message */
|
/* Send a broadcast message */
|
||||||
#define UHUB_EVENT_BROADCAST 0x2000
|
#define UHUB_EVENT_BROADCAST 0x2000
|
||||||
|
|
||||||
/* Shutdown hub */
|
|
||||||
#define UHUB_EVENT_HUB_SHUTDOWN 0x3001
|
|
||||||
|
|
||||||
/* Statistics, OOM, reconfigure */
|
/* Statistics, OOM, reconfigure */
|
||||||
#define UHUB_EVENT_STATISTICS 0x4000
|
#define UHUB_EVENT_STATISTICS 0x4000
|
||||||
#define UHUB_EVENT_OUT_OF_MEMORY 0x4001
|
#define UHUB_EVENT_OUT_OF_MEMORY 0x4001
|
||||||
#define UHUB_EVENT_RECONFIGURE 0x4002
|
#define UHUB_EVENT_RECONFIGURE 0x4002
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_EVENT_ID_H */
|
#endif /* HAVE_UHUB_EVENT_ID_H */
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
#ifdef EQ_DEBUG
|
#ifdef EQ_DEBUG
|
||||||
static void eq_debug(const char* prefix, struct event_data* data)
|
static void eq_debug(const char* prefix, struct event_data* data)
|
||||||
{
|
{
|
||||||
LOG_DUMP(">>> %s: %p, id: %x, flags=%d\n", prefix, data, data->id, data->flags);
|
printf(">>> %s: %p, id: %x, flags=%d\n", prefix, data, data->id, data->flags);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ void event_queue_post(struct event_queue* queue, struct event_data* message)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_ERROR("event_queue_post: OUT OF MEMORY");
|
hub_log(log_error, "event_queue_post: OUT OF MEMORY");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
889
src/hub.c
Normal file
889
src/hub.c
Normal file
@@ -0,0 +1,889 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
int hub_handle_message(struct hub_info* hub, struct user* u, const char* line, size_t length)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct adc_message* cmd = 0;
|
||||||
|
|
||||||
|
#ifdef NETWORK_DUMP_DEBUG
|
||||||
|
hub_log(log_protocol, "recv %s: %s", sid_to_string(u->id.sid), line);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (user_is_disconnecting(u))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
cmd = adc_msg_parse_verify(u, line, length);
|
||||||
|
if (cmd)
|
||||||
|
{
|
||||||
|
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_DINF:
|
||||||
|
case ADC_CMD_EINF:
|
||||||
|
case ADC_CMD_FINF:
|
||||||
|
/* 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:
|
||||||
|
ret = hub_handle_chat_message(hub, u, cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CMD_BSCH:
|
||||||
|
case ADC_CMD_DSCH:
|
||||||
|
case ADC_CMD_ESCH:
|
||||||
|
case ADC_CMD_FSCH:
|
||||||
|
case ADC_CMD_DRES:
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (user_is_logged_in(u))
|
||||||
|
{
|
||||||
|
ret = route_message(u, cmd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
adc_msg_free(cmd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!user_is_logged_in(u))
|
||||||
|
{
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int hub_handle_support(struct hub_info* hub, struct user* u, struct adc_message* cmd)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int index = 0;
|
||||||
|
int ok = 1;
|
||||||
|
char* arg = adc_msg_get_argument(cmd, index);
|
||||||
|
struct timeval timeout = { TIMEOUT_HANDSHAKE, 0 };
|
||||||
|
|
||||||
|
if (hub->status == hub_status_disabled && u->state == state_protocol)
|
||||||
|
{
|
||||||
|
on_login_failure(hub, u, status_msg_hub_disabled);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (arg)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (strlen(arg) == 6)
|
||||||
|
{
|
||||||
|
fourcc_t fourcc = FOURCC(arg[2], arg[3], arg[4], arg[5]);
|
||||||
|
if (strncmp(arg, ADC_SUP_FLAG_ADD, 2) == 0)
|
||||||
|
{
|
||||||
|
user_support_add(u, fourcc);
|
||||||
|
}
|
||||||
|
else if (strncmp(arg, ADC_SUP_FLAG_REMOVE, 2) == 0)
|
||||||
|
{
|
||||||
|
user_support_remove(u, fourcc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
hub_free(arg);
|
||||||
|
arg = adc_msg_get_argument(cmd, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u->state == state_protocol)
|
||||||
|
{
|
||||||
|
if (index == 0) ok = 0; /* Need to support *SOMETHING*, at least BASE */
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
hub_send_handshake(hub, u);
|
||||||
|
if (u->ev_read)
|
||||||
|
event_add(u->ev_read, &timeout);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* disconnect user. Do not send crap during initial handshake! */
|
||||||
|
user_disconnect(u, quit_logon_error);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int hub_handle_password(struct hub_info* hub, struct user* u, struct adc_message* cmd)
|
||||||
|
{
|
||||||
|
char* password = adc_msg_get_argument(cmd, 0);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (u->state == state_verify)
|
||||||
|
{
|
||||||
|
if (password_verify(u, password))
|
||||||
|
{
|
||||||
|
on_login_success(hub, u);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
on_login_failure(hub, u, status_msg_auth_invalid_password);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hub_free(password);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int hub_handle_chat_message(struct hub_info* hub, struct user* u, struct adc_message* cmd)
|
||||||
|
{
|
||||||
|
char* message = adc_msg_get_argument(cmd, 0);
|
||||||
|
int ret = 0;
|
||||||
|
int relay = 1;
|
||||||
|
|
||||||
|
/* TODO: Check for hub-commands here. Set relay to 0 and the message will not be sent to other users. */
|
||||||
|
if (message[0] == '!' || message[0] == '+')
|
||||||
|
{
|
||||||
|
relay = command_dipatcher(hub, u, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relay && user_is_logged_in(u))
|
||||||
|
{
|
||||||
|
/* adc_msg_remove_named_argument(cmd, "PM"); */
|
||||||
|
ret = route_message(u, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(message);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hub_send_support(struct hub_info* hub, struct user* u)
|
||||||
|
{
|
||||||
|
if (user_is_connecting(u) || user_is_logged_in(u))
|
||||||
|
{
|
||||||
|
route_to_user(u, hub->command_support);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hub_send_sid(struct hub_info* hub, struct user* u)
|
||||||
|
{
|
||||||
|
struct adc_message* command;
|
||||||
|
if (user_is_connecting(u))
|
||||||
|
{
|
||||||
|
command = adc_msg_construct(ADC_CMD_ISID, 10);
|
||||||
|
u->id.sid = uman_get_free_sid(hub);
|
||||||
|
adc_msg_add_argument(command, (const char*) sid_to_string(u->id.sid));
|
||||||
|
route_to_user(u, command);
|
||||||
|
adc_msg_free(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hub_send_ping(struct hub_info* hub, struct user* user)
|
||||||
|
{
|
||||||
|
/* This will just send a newline, despite appearing to do more below. */
|
||||||
|
struct adc_message* ping = adc_msg_construct(0, 0);
|
||||||
|
ping->cache[0] = '\n';
|
||||||
|
ping->cache[1] = 0;
|
||||||
|
ping->length = 1;
|
||||||
|
ping->priority = 1;
|
||||||
|
route_to_user(user, ping);
|
||||||
|
adc_msg_free(ping);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hub_send_hubinfo(struct hub_info* hub, struct user* u)
|
||||||
|
{
|
||||||
|
struct adc_message* info = adc_msg_copy(hub->command_info);
|
||||||
|
int value = 0;
|
||||||
|
|
||||||
|
if (user_flag_get(u, feature_ping))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
FIXME: These are missing:
|
||||||
|
HH - Hub Host address ( DNS or IP )
|
||||||
|
WS - Hub Website
|
||||||
|
NE - Hub Network
|
||||||
|
OW - Hub Owner name
|
||||||
|
*/
|
||||||
|
adc_msg_add_named_argument(info, "UC", uhub_itoa(hub_get_user_count(hub)));
|
||||||
|
adc_msg_add_named_argument(info, "MC", uhub_itoa(hub_get_max_user_count(hub)));
|
||||||
|
adc_msg_add_named_argument(info, "SS", uhub_ulltoa(hub_get_shared_size(hub)));
|
||||||
|
adc_msg_add_named_argument(info, "SF", uhub_itoa(hub_get_shared_files(hub)));
|
||||||
|
|
||||||
|
/* Maximum/minimum share size */
|
||||||
|
value = hub_get_max_share(hub);
|
||||||
|
if (value) adc_msg_add_named_argument(info, "XS", uhub_itoa(value));
|
||||||
|
value = hub_get_min_share(hub);
|
||||||
|
if (value) adc_msg_add_named_argument(info, "MS", uhub_itoa(value));
|
||||||
|
|
||||||
|
/* Maximum/minimum upload slots allowed per user */
|
||||||
|
value = hub_get_max_slots(hub);
|
||||||
|
if (value) adc_msg_add_named_argument(info, "XL", uhub_itoa(value));
|
||||||
|
value = hub_get_min_slots(hub);
|
||||||
|
if (value) adc_msg_add_named_argument(info, "ML", uhub_itoa(value));
|
||||||
|
|
||||||
|
/* guest users must be on min/max hubs */
|
||||||
|
value = hub_get_max_hubs_user(hub);
|
||||||
|
if (value) adc_msg_add_named_argument(info, "XU", uhub_itoa(value));
|
||||||
|
value = hub_get_min_hubs_user(hub);
|
||||||
|
if (value) adc_msg_add_named_argument(info, "MU", uhub_itoa(value));
|
||||||
|
|
||||||
|
/* registered users must be on min/max hubs */
|
||||||
|
value = hub_get_max_hubs_reg(hub);
|
||||||
|
if (value) adc_msg_add_named_argument(info, "XR", uhub_itoa(value));
|
||||||
|
value = hub_get_min_hubs_reg(hub);
|
||||||
|
if (value) adc_msg_add_named_argument(info, "MR", uhub_itoa(value));
|
||||||
|
|
||||||
|
/* operators must be on min/max hubs */
|
||||||
|
value = hub_get_max_hubs_op(hub);
|
||||||
|
if (value) adc_msg_add_named_argument(info, "XO", uhub_itoa(value));
|
||||||
|
value = hub_get_min_hubs_op(hub);
|
||||||
|
if (value) adc_msg_add_named_argument(info, "MO", uhub_itoa(value));
|
||||||
|
|
||||||
|
/* uptime in seconds */
|
||||||
|
adc_msg_add_named_argument(info, "UP", uhub_itoa((int) difftime(time(0), hub->tm_started)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user_is_connecting(u) || user_is_logged_in(u))
|
||||||
|
{
|
||||||
|
route_to_user(u, info);
|
||||||
|
}
|
||||||
|
adc_msg_free(info);
|
||||||
|
|
||||||
|
/* Only send banner when connecting */
|
||||||
|
if (hub->config->show_banner && user_is_connecting(u))
|
||||||
|
{
|
||||||
|
route_to_user(u, hub->command_banner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hub_send_handshake(struct hub_info* hub, struct user* u)
|
||||||
|
{
|
||||||
|
hub_send_support(hub, u);
|
||||||
|
hub_send_sid(hub, u);
|
||||||
|
hub_send_hubinfo(hub, u);
|
||||||
|
|
||||||
|
if (!user_is_disconnecting(u))
|
||||||
|
{
|
||||||
|
user_set_state(u, state_identify);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hub_send_motd(struct hub_info* hub, struct user* u)
|
||||||
|
{
|
||||||
|
if (hub->command_motd)
|
||||||
|
{
|
||||||
|
route_to_user(u, hub->command_motd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hub_send_password_challenge(struct hub_info* hub, struct user* u)
|
||||||
|
{
|
||||||
|
struct adc_message* igpa;
|
||||||
|
igpa = adc_msg_construct(ADC_CMD_IGPA, 38);
|
||||||
|
adc_msg_add_argument(igpa, password_generate_challenge(u));
|
||||||
|
user_set_state(u, state_verify);
|
||||||
|
route_to_user(u, igpa);
|
||||||
|
adc_msg_free(igpa);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hub_event_dispatcher(void* callback_data, struct event_data* message)
|
||||||
|
{
|
||||||
|
struct hub_info* hub = (struct hub_info*) callback_data;
|
||||||
|
/*
|
||||||
|
hub_log(log_trace, "hub_event_dispatcher: %x (ptr=%p)", message->id, message->ptr);
|
||||||
|
*/
|
||||||
|
|
||||||
|
switch (message->id)
|
||||||
|
{
|
||||||
|
case UHUB_EVENT_USER_JOIN:
|
||||||
|
{
|
||||||
|
if (user_is_disconnecting((struct user*) message->ptr))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (message->flags)
|
||||||
|
{
|
||||||
|
hub_send_password_challenge(hub, (struct user*) message->ptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
on_login_success(hub, (struct user*) message->ptr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case UHUB_EVENT_USER_QUIT:
|
||||||
|
{
|
||||||
|
uman_remove(hub, (struct user*) message->ptr);
|
||||||
|
uman_send_quit_message((struct user*) message->ptr);
|
||||||
|
on_logout_user(hub, (struct user*) message->ptr);
|
||||||
|
user_schedule_destroy((struct user*) message->ptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case UHUB_EVENT_USER_DESTROY:
|
||||||
|
{
|
||||||
|
hub_log(log_trace, "hub_event_dispatcher: UHUB_EVENT_USER_DESTROY (ptr=%p)", message->ptr);
|
||||||
|
user_destroy((struct user*) message->ptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* FIXME: ignored */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct hub_info* hub_start_service(struct hub_config* config)
|
||||||
|
{
|
||||||
|
struct hub_info* hub = 0;
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
socklen_t sockaddr_size;
|
||||||
|
int server_tcp, ret, ipv6_supported, af;
|
||||||
|
char address_buf[INET6_ADDRSTRLEN+1];
|
||||||
|
|
||||||
|
hub = hub_malloc_zero(sizeof(struct hub_info));
|
||||||
|
if (!hub)
|
||||||
|
{
|
||||||
|
hub_log(log_fatal, "Unable to allocate memory for hub");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hub->tm_started = time(0);
|
||||||
|
|
||||||
|
ipv6_supported = net_is_ipv6_supported();
|
||||||
|
|
||||||
|
if (ipv6_supported)
|
||||||
|
hub_log(log_debug, "IPv6 supported.");
|
||||||
|
else
|
||||||
|
hub_log(log_debug, "IPv6 not supported.");
|
||||||
|
|
||||||
|
if (ip_convert_address(config->server_bind_addr, config->server_port, (struct sockaddr*) &addr, &sockaddr_size) == -1)
|
||||||
|
{
|
||||||
|
hub_free(hub);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
af = addr.ss_family;
|
||||||
|
if (af == AF_INET)
|
||||||
|
{
|
||||||
|
net_address_to_string(AF_INET, &((struct sockaddr_in*) &addr)->sin_addr, address_buf, INET6_ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
else if (af == AF_INET6)
|
||||||
|
{
|
||||||
|
net_address_to_string(AF_INET6, &((struct sockaddr_in6*) &addr)->sin6_addr, address_buf, INET6_ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef LIBEVENT_1_4
|
||||||
|
hub->evbase = event_base_new();
|
||||||
|
#else
|
||||||
|
hub->evbase = event_init();
|
||||||
|
#endif
|
||||||
|
if (!hub->evbase)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "Unable to initialize libevent.");
|
||||||
|
hub_free(hub);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hub_log(log_info, "Starting " PRODUCT "/" VERSION ", listening on %s:%d...", address_buf, config->server_port);
|
||||||
|
hub_log(log_debug, "Using libevent %s, backend: %s", event_get_version(), event_get_method());
|
||||||
|
|
||||||
|
server_tcp = net_socket_create(af, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (server_tcp == -1)
|
||||||
|
{
|
||||||
|
event_base_free(hub->evbase);
|
||||||
|
hub_free(hub);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = net_set_reuseaddress(server_tcp, 1);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
event_base_free(hub->evbase);
|
||||||
|
hub_free(hub);
|
||||||
|
net_close(server_tcp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = net_set_nonblocking(server_tcp, 1);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
event_base_free(hub->evbase);
|
||||||
|
hub_free(hub);
|
||||||
|
net_close(server_tcp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = net_bind(server_tcp, (struct sockaddr*) &addr, sockaddr_size);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
hub_log(log_fatal, "hub_start_service(): Unable to bind to TCP local address. errno=%d, str=%s", net_error(), net_error_string(net_error()));
|
||||||
|
event_base_free(hub->evbase);
|
||||||
|
hub_free(hub);
|
||||||
|
net_close(server_tcp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = net_listen(server_tcp, SERVER_BACKLOG);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
hub_log(log_fatal, "hub_start_service(): Unable to listen to socket");
|
||||||
|
event_base_free(hub->evbase);
|
||||||
|
hub_free(hub);
|
||||||
|
net_close(server_tcp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hub->fd_tcp = server_tcp;
|
||||||
|
hub->config = config;
|
||||||
|
hub->users = NULL;
|
||||||
|
|
||||||
|
if (uman_init(hub) == -1)
|
||||||
|
{
|
||||||
|
hub_free(hub);
|
||||||
|
net_close(server_tcp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
event_set(&hub->ev_accept, hub->fd_tcp, EV_READ | EV_PERSIST, net_on_accept, hub);
|
||||||
|
event_base_set(hub->evbase, &hub->ev_accept);
|
||||||
|
if (event_add(&hub->ev_accept, NULL) == -1)
|
||||||
|
{
|
||||||
|
uman_shutdown(hub);
|
||||||
|
hub_free(hub);
|
||||||
|
net_close(server_tcp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event_queue_initialize(&hub->queue, hub_event_dispatcher, (void*) hub) == -1)
|
||||||
|
{
|
||||||
|
uman_shutdown(hub);
|
||||||
|
hub_free(hub);
|
||||||
|
net_close(server_tcp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hub->status = hub_status_running;
|
||||||
|
|
||||||
|
return hub;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hub_shutdown_service(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
hub_log(log_trace, "hub_shutdown_service()");
|
||||||
|
|
||||||
|
event_queue_shutdown(hub->queue);
|
||||||
|
event_del(&hub->ev_accept);
|
||||||
|
net_close(hub->fd_tcp);
|
||||||
|
uman_shutdown(hub);
|
||||||
|
hub->status = hub_status_stopped;
|
||||||
|
event_base_free(hub->evbase);
|
||||||
|
hub_free(hub);
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
hub->acl = acl;
|
||||||
|
hub->command_info = adc_msg_construct(ADC_CMD_IINF, 15 + strlen(SERVER));
|
||||||
|
if (hub->command_info)
|
||||||
|
{
|
||||||
|
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_CLIENT_TYPE, ADC_CLIENT_TYPE_HUB);
|
||||||
|
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_USER_AGENT, SERVER);
|
||||||
|
|
||||||
|
tmp = adc_msg_escape(hub->config->hub_name);
|
||||||
|
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_NICK, tmp);
|
||||||
|
hub_free(tmp);
|
||||||
|
|
||||||
|
tmp = adc_msg_escape(hub->config->hub_description);
|
||||||
|
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION, tmp);
|
||||||
|
hub_free(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (Re-)read the message of the day */
|
||||||
|
hub->command_motd = 0;
|
||||||
|
fd = open(hub->config->file_motd, 0);
|
||||||
|
if (fd != -1)
|
||||||
|
{
|
||||||
|
ret = read(fd, buf, MAX_RECV_BUF);
|
||||||
|
if (ret > 0)
|
||||||
|
{
|
||||||
|
buf[ret] = 0;
|
||||||
|
tmp = adc_msg_escape(buf);
|
||||||
|
hub->command_motd = adc_msg_construct(ADC_CMD_IMSG, 6 + strlen(tmp));
|
||||||
|
adc_msg_add_argument(hub->command_motd, tmp);
|
||||||
|
hub_free(tmp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
hub->command_support = adc_msg_construct(ADC_CMD_ISUP, 6 + strlen(ADC_PROTO_SUPPORT));
|
||||||
|
if (hub->command_support)
|
||||||
|
{
|
||||||
|
adc_msg_add_argument(hub->command_support, ADC_PROTO_SUPPORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
hub->command_banner = adc_msg_construct(ADC_CMD_ISTA, 25 + strlen(SERVER));
|
||||||
|
if (hub->command_banner)
|
||||||
|
{
|
||||||
|
adc_msg_add_argument(hub->command_banner, "000 Powered\\sby\\s" SERVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
hub->status = (hub->config->hub_enabled ? hub_status_running : hub_status_disabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hub_free_variables(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
adc_msg_free(hub->command_info);
|
||||||
|
adc_msg_free(hub->command_banner);
|
||||||
|
|
||||||
|
if (hub->command_motd)
|
||||||
|
adc_msg_free(hub->command_motd);
|
||||||
|
|
||||||
|
adc_msg_free(hub->command_support);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 1 if nickname is in use, or 0 if not used.
|
||||||
|
*/
|
||||||
|
static inline int is_nick_in_use(struct hub_info* hub, const char* nick)
|
||||||
|
{
|
||||||
|
struct user* lookup = uman_get_user_by_nick(hub, nick);
|
||||||
|
if (lookup)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 1 if CID is in use, or 0 if not used.
|
||||||
|
*/
|
||||||
|
static inline int is_cid_in_use(struct hub_info* hub, const char* cid)
|
||||||
|
{
|
||||||
|
struct user* lookup = uman_get_user_by_cid(hub, cid);
|
||||||
|
if (lookup)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void set_status_code(enum msg_status_level level, int code, char buffer[4])
|
||||||
|
{
|
||||||
|
buffer[0] = ('0' + (int) level);
|
||||||
|
buffer[1] = ('0' + (code / 10));
|
||||||
|
buffer[2] = ('0' + (code % 10));
|
||||||
|
buffer[3] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param hub The hub instance this message is sent from.
|
||||||
|
* @param user The user this message is sent to.
|
||||||
|
* @param msg See enum status_message
|
||||||
|
* @param level See enum status_level
|
||||||
|
*/
|
||||||
|
void hub_send_status(struct hub_info* hub, struct user* user, enum status_message msg, enum msg_status_level level)
|
||||||
|
{
|
||||||
|
struct hub_config* cfg = hub->config;
|
||||||
|
struct adc_message* cmd = adc_msg_construct(ADC_CMD_ISTA, 6);
|
||||||
|
if (!cmd) return;
|
||||||
|
char code[4];
|
||||||
|
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
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
#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(user, cmd);
|
||||||
|
adc_msg_free(cmd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* hub_get_status_message(struct hub_info* hub, enum status_message msg)
|
||||||
|
{
|
||||||
|
#define STATUS(MSG) case status_ ## MSG : return cfg->MSG; break
|
||||||
|
struct hub_config* cfg = hub->config;
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
STATUS(msg_hub_full);
|
||||||
|
STATUS(msg_hub_disabled);
|
||||||
|
STATUS(msg_hub_registered_users_only);
|
||||||
|
STATUS(msg_inf_error_nick_missing);
|
||||||
|
STATUS(msg_inf_error_nick_multiple);
|
||||||
|
STATUS(msg_inf_error_nick_invalid);
|
||||||
|
STATUS(msg_inf_error_nick_long);
|
||||||
|
STATUS(msg_inf_error_nick_short);
|
||||||
|
STATUS(msg_inf_error_nick_spaces);
|
||||||
|
STATUS(msg_inf_error_nick_bad_chars);
|
||||||
|
STATUS(msg_inf_error_nick_not_utf8);
|
||||||
|
STATUS(msg_inf_error_nick_taken);
|
||||||
|
STATUS(msg_inf_error_nick_restricted);
|
||||||
|
STATUS(msg_inf_error_cid_invalid);
|
||||||
|
STATUS(msg_inf_error_cid_missing);
|
||||||
|
STATUS(msg_inf_error_cid_taken);
|
||||||
|
STATUS(msg_inf_error_pid_missing);
|
||||||
|
STATUS(msg_inf_error_pid_invalid);
|
||||||
|
STATUS(msg_ban_permanently);
|
||||||
|
STATUS(msg_ban_temporarily);
|
||||||
|
STATUS(msg_auth_invalid_password);
|
||||||
|
STATUS(msg_auth_user_not_found);
|
||||||
|
STATUS(msg_error_no_memory);
|
||||||
|
STATUS(msg_user_share_size_low);
|
||||||
|
STATUS(msg_user_share_size_high);
|
||||||
|
STATUS(msg_user_slots_low);
|
||||||
|
STATUS(msg_user_slots_high);
|
||||||
|
STATUS(msg_user_hub_limit_low);
|
||||||
|
STATUS(msg_user_hub_limit_high);
|
||||||
|
}
|
||||||
|
#undef STATUS
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* hub_get_status_message_log(struct hub_info* hub, enum status_message msg)
|
||||||
|
{
|
||||||
|
#define STATUS(MSG) case status_ ## MSG : return #MSG; break
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
STATUS(msg_hub_full);
|
||||||
|
STATUS(msg_hub_disabled);
|
||||||
|
STATUS(msg_hub_registered_users_only);
|
||||||
|
STATUS(msg_inf_error_nick_missing);
|
||||||
|
STATUS(msg_inf_error_nick_multiple);
|
||||||
|
STATUS(msg_inf_error_nick_invalid);
|
||||||
|
STATUS(msg_inf_error_nick_long);
|
||||||
|
STATUS(msg_inf_error_nick_short);
|
||||||
|
STATUS(msg_inf_error_nick_spaces);
|
||||||
|
STATUS(msg_inf_error_nick_bad_chars);
|
||||||
|
STATUS(msg_inf_error_nick_not_utf8);
|
||||||
|
STATUS(msg_inf_error_nick_taken);
|
||||||
|
STATUS(msg_inf_error_nick_restricted);
|
||||||
|
STATUS(msg_inf_error_cid_invalid);
|
||||||
|
STATUS(msg_inf_error_cid_missing);
|
||||||
|
STATUS(msg_inf_error_cid_taken);
|
||||||
|
STATUS(msg_inf_error_pid_missing);
|
||||||
|
STATUS(msg_inf_error_pid_invalid);
|
||||||
|
STATUS(msg_ban_permanently);
|
||||||
|
STATUS(msg_ban_temporarily);
|
||||||
|
STATUS(msg_auth_invalid_password);
|
||||||
|
STATUS(msg_auth_user_not_found);
|
||||||
|
STATUS(msg_error_no_memory);
|
||||||
|
STATUS(msg_user_share_size_low);
|
||||||
|
STATUS(msg_user_share_size_high);
|
||||||
|
STATUS(msg_user_slots_low);
|
||||||
|
STATUS(msg_user_slots_high);
|
||||||
|
STATUS(msg_user_hub_limit_low);
|
||||||
|
STATUS(msg_user_hub_limit_high);
|
||||||
|
}
|
||||||
|
#undef STATUS
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t hub_get_user_count(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
return hub->users->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t hub_get_max_user_count(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
return hub->config->max_users;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t hub_get_shared_size(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
return hub->users->shared_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t hub_get_shared_files(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
return hub->users->shared_files;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t hub_get_min_share(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
return 1024 * 1024 * hub->config->limit_min_share;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t hub_get_max_share(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
return 1024 * 1024 * hub->config->limit_max_share;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t hub_get_min_slots(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
return hub->config->limit_min_slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t hub_get_max_slots(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
return hub->config->limit_max_slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t hub_get_max_hubs_total(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
return hub->config->limit_max_hubs;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t hub_get_max_hubs_user(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
return hub->config->limit_max_hubs_user;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t hub_get_min_hubs_user(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
return hub->config->limit_min_hubs_user;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t hub_get_max_hubs_reg(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
return hub->config->limit_max_hubs_reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t hub_get_min_hubs_reg(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
return hub->config->limit_min_hubs_reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t hub_get_max_hubs_op(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
return hub->config->limit_max_hubs_op;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t hub_get_min_hubs_op(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
return hub->config->limit_min_hubs_op;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hub_event_loop(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ret = event_base_loop(hub->evbase, EVLOOP_ONCE);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
hub_log(log_debug, "event_base_loop returned: %d", (int) ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
event_queue_process(hub->queue);
|
||||||
|
}
|
||||||
|
while (hub->status == hub_status_running || hub->status == hub_status_disabled);
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -53,10 +53,6 @@ enum status_message
|
|||||||
status_msg_user_hub_limit_low = -44, /* Use is on too few hubs. */
|
status_msg_user_hub_limit_low = -44, /* Use is on too few hubs. */
|
||||||
status_msg_user_hub_limit_high = -45, /* Use is on too many hubs. */
|
status_msg_user_hub_limit_high = -45, /* Use is on too many hubs. */
|
||||||
|
|
||||||
status_msg_proto_no_common_hash = -50, /* No common hash algorithms */
|
|
||||||
status_msg_proto_obsolete_adc0 = -51, /* Client is using an obsolete protocol version */
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -83,37 +79,23 @@ struct hub_stats
|
|||||||
size_t net_rx_total;
|
size_t net_rx_total;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hub_logout_info
|
|
||||||
{
|
|
||||||
time_t time;
|
|
||||||
char cid[MAX_CID_LEN+1];
|
|
||||||
char nick[MAX_NICK_LEN+1];
|
|
||||||
struct ip_addr_encap addr;
|
|
||||||
enum user_quit_reason reason;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct hub_info
|
struct hub_info
|
||||||
{
|
{
|
||||||
struct net_connection* server;
|
int fd_tcp;
|
||||||
struct linked_list* server_alt_ports;
|
struct event ev_accept;
|
||||||
|
struct event ev_timer;
|
||||||
struct hub_stats stats;
|
struct hub_stats stats;
|
||||||
struct event_queue* queue;
|
struct event_queue* queue;
|
||||||
|
struct event_base* evbase;
|
||||||
struct hub_config* config;
|
struct hub_config* config;
|
||||||
struct hub_user_manager* users;
|
struct user_manager* users;
|
||||||
struct acl_handle* acl;
|
struct acl_handle* acl;
|
||||||
struct adc_message* command_info; /* The hub's INF command */
|
struct adc_message* command_info; /* The hub's INF command */
|
||||||
struct adc_message* command_support; /* The hub's SUP command */
|
struct adc_message* command_support; /* The hub's SUP command */
|
||||||
struct adc_message* command_motd; /* The message of the day */
|
struct adc_message* command_motd; /* The message of the day */
|
||||||
struct adc_message* command_rules; /* The hub rules */
|
|
||||||
struct adc_message* command_banner; /* The default welcome message */
|
struct adc_message* command_banner; /* The default welcome message */
|
||||||
time_t tm_started;
|
time_t tm_started;
|
||||||
int status;
|
int status;
|
||||||
char* recvbuf; /* Global receive buffer */
|
|
||||||
char* sendbuf; /* Global send buffer */
|
|
||||||
|
|
||||||
struct linked_list* chat_history; /* Chat history */
|
|
||||||
struct linked_list* logout_info; /* Log of people logging out. */
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
SSL_METHOD* ssl_method;
|
SSL_METHOD* ssl_method;
|
||||||
SSL_CTX* ssl_ctx;
|
SSL_CTX* ssl_ctx;
|
||||||
@@ -128,104 +110,87 @@ struct hub_info
|
|||||||
*
|
*
|
||||||
* @return 0 on success, -1 on error
|
* @return 0 on success, -1 on error
|
||||||
*/
|
*/
|
||||||
extern int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* message, size_t length);
|
extern int hub_handle_message(struct hub_info* hub, struct user* u, const char* message, size_t length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle protocol support/subscription messages received clients.
|
* Handle protocol support/subscription messages received clients.
|
||||||
*
|
*
|
||||||
* @return 0 on success, -1 on error
|
* @return 0 on success, -1 on error
|
||||||
*/
|
*/
|
||||||
extern int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
|
extern int hub_handle_support(struct hub_info* hub, struct user* u, struct adc_message* cmd);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle password messages received from clients.
|
* Handle password messages received from clients.
|
||||||
*
|
*
|
||||||
* @return 0 on success, -1 on error
|
* @return 0 on success, -1 on error
|
||||||
*/
|
*/
|
||||||
extern int hub_handle_password(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
|
extern int hub_handle_password(struct hub_info* hub, struct user* u, struct adc_message* cmd);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle chat messages received from clients.
|
* Handle chat messages received from clients.
|
||||||
* @return 0 on success, -1 on error.
|
* @return 0 on success, -1 on error.
|
||||||
*/
|
*/
|
||||||
extern int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
|
extern int hub_handle_chat_message(struct hub_info* hub, struct user* u, struct adc_message* cmd);
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a chat message to the chat history
|
|
||||||
*/
|
|
||||||
extern void hub_chat_history_add(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear the chat history.
|
|
||||||
*/
|
|
||||||
extern void hub_chat_history_clear(struct hub_info* hub);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used internally by hub_handle_info
|
* Used internally by hub_handle_info
|
||||||
* @return 1 if nickname is OK, or 0 if nickname is not accepted.
|
* @return 1 if nickname is OK, or 0 if nickname is not accepted.
|
||||||
*/
|
*/
|
||||||
extern int hub_handle_info_check_nick(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
|
extern int hub_handle_info_check_nick(struct hub_info* hub, struct user* u, struct adc_message* cmd);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used internally by hub_handle_info
|
* Used internally by hub_handle_info
|
||||||
* @return 1 if CID/PID is OK, or 0 if not valid.
|
* @return 1 if CID/PID is OK, or 0 if not valid.
|
||||||
*/
|
*/
|
||||||
extern int hub_handle_info_check_cid(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
|
extern int hub_handle_info_check_cid(struct hub_info* hub, struct user* u, struct adc_message* cmd);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send the support line for the hub to a particular user.
|
* Send the support line for the hub to a particular user.
|
||||||
* Only used during the initial handshake.
|
* Only used during the initial handshake.
|
||||||
*/
|
*/
|
||||||
extern void hub_send_support(struct hub_info* hub, struct hub_user* u);
|
extern void hub_send_support(struct hub_info* hub, struct user* u);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a message assigning a SID for a user.
|
* Send a message assigning a SID for a user.
|
||||||
* This is only sent after hub_send_support() during initial handshake.
|
* This is only sent after hub_send_support() during initial handshake.
|
||||||
*/
|
*/
|
||||||
extern void hub_send_sid(struct hub_info* hub, struct hub_user* u);
|
extern void hub_send_sid(struct hub_info* hub, struct user* u);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a 'ping' message to user.
|
* Send a 'ping' message to user.
|
||||||
*/
|
*/
|
||||||
extern void hub_send_ping(struct hub_info* hub, struct hub_user* user);
|
extern void hub_send_ping(struct hub_info* hub, struct user* user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a message containing hub information to a particular user.
|
* Send a message containing hub information to a particular user.
|
||||||
* This is sent during user connection, but can safely be sent at any
|
* This is sent during user connection, but can safely be sent at any
|
||||||
* point later.
|
* point later.
|
||||||
*/
|
*/
|
||||||
extern void hub_send_hubinfo(struct hub_info* hub, struct hub_user* u);
|
extern void hub_send_hubinfo(struct hub_info* hub, struct user* u);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send handshake. This basically calls
|
* Send handshake. This basically calls
|
||||||
* hub_send_support() and hub_send_sid()
|
* hub_send_support() and hub_send_sid()
|
||||||
*/
|
*/
|
||||||
extern void hub_send_handshake(struct hub_info* hub, struct hub_user* u);
|
extern void hub_send_handshake(struct hub_info* hub, struct user* u);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a welcome message containing the message of the day to
|
* Send a welcome message containing the message of the day to
|
||||||
* one particular user. This can be sent in any point in time.
|
* one particular user. This can be sent in any point in time.
|
||||||
* @return 1 if the motd were sent.
|
|
||||||
*/
|
*/
|
||||||
extern int hub_send_motd(struct hub_info* hub, struct hub_user* u);
|
extern void hub_send_motd(struct hub_info* hub, struct user* u);
|
||||||
|
|
||||||
/**
|
|
||||||
* Send the rules if configured.
|
|
||||||
* @return 1 if the rules were sent.
|
|
||||||
*/
|
|
||||||
extern int hub_send_rules(struct hub_info* hub, struct hub_user* u);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a password challenge to a user.
|
* Send a password challenge to a user.
|
||||||
* This is only used if the user tries to access the hub using a
|
* This is only used if the user tries to access the hub using a
|
||||||
* password protected nick name.
|
* password protected nick name.
|
||||||
*/
|
*/
|
||||||
extern void hub_send_password_challenge(struct hub_info* hub, struct hub_user* u);
|
extern void hub_send_password_challenge(struct hub_info* hub, struct user* u);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a status_message to a user.
|
* Sends a status_message to a user.
|
||||||
*/
|
*/
|
||||||
extern void hub_send_status(struct hub_info*, struct hub_user* user, enum status_message msg, enum msg_status_level level);
|
extern void hub_send_status(struct hub_info*, struct user* user, enum status_message msg, enum msg_status_level level);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates memory, initializes the hub based on the configuration,
|
* Allocates memory, initializes the hub based on the configuration,
|
||||||
@@ -353,21 +318,6 @@ extern void hub_schedule_runslice(struct hub_info* hub);
|
|||||||
*/
|
*/
|
||||||
extern void hub_event_loop(struct hub_info* hub);
|
extern void hub_event_loop(struct hub_info* hub);
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedule destroying a user.
|
|
||||||
*/
|
|
||||||
extern void hub_schedule_destroy_user(struct hub_info* hub, struct hub_user* user);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disconnect a user from the hub.
|
|
||||||
*/
|
|
||||||
extern void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int reason);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Log a user logging out.
|
|
||||||
*/
|
|
||||||
extern void hub_logout_log(struct hub_info* hub, struct hub_user* user);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_HUB_H */
|
#endif /* HAVE_UHUB_HUB_H */
|
||||||
|
|
||||||
122
src/hubevent.c
Normal file
122
src/hubevent.c
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
static void log_user_login(struct user* u)
|
||||||
|
{
|
||||||
|
const char* cred = get_user_credential_string(u->credentials);
|
||||||
|
const char* addr = ip_convert_to_string(&u->ipaddr);
|
||||||
|
hub_log(log_user, "LoginOK %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, cred, u->user_agent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_user_login_error(struct user* u, enum status_message msg)
|
||||||
|
{
|
||||||
|
const char* addr = ip_convert_to_string(&u->ipaddr);
|
||||||
|
const char* message = hub_get_status_message_log(u->hub, msg);
|
||||||
|
hub_log(log_user, "LoginError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_user_logout(struct user* u, const char* message)
|
||||||
|
{
|
||||||
|
const char* addr = ip_convert_to_string(&u->ipaddr);
|
||||||
|
hub_log(log_user, "Logout %s/%s %s \"%s\" (%s)", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_user_nick_change(struct user* u, const char* nick)
|
||||||
|
{
|
||||||
|
const char* addr = ip_convert_to_string(&u->ipaddr);
|
||||||
|
hub_log(log_user, "NickChange %s/%s %s \"%s\" -> \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, nick);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Send MOTD, do logging etc */
|
||||||
|
void on_login_success(struct hub_info* hub, struct user* u)
|
||||||
|
{
|
||||||
|
struct timeval timeout = { TIMEOUT_IDLE, 0 };
|
||||||
|
|
||||||
|
/* Send user list of all existing users */
|
||||||
|
if (!uman_send_user_list(u))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Mark as being in the normal state, and add user to the user list */
|
||||||
|
user_set_state(u, state_normal);
|
||||||
|
uman_add(hub, u);
|
||||||
|
|
||||||
|
/* Print log message */
|
||||||
|
log_user_login(u);
|
||||||
|
|
||||||
|
/* Announce new user to all connected users */
|
||||||
|
if (user_is_logged_in(u))
|
||||||
|
route_info_message(u);
|
||||||
|
|
||||||
|
/* Send message of the day (if any) */
|
||||||
|
if (user_is_logged_in(u)) /* Previous send() can fail! */
|
||||||
|
hub_send_motd(hub, u);
|
||||||
|
|
||||||
|
/* reset to idle timeout */
|
||||||
|
if (u->ev_read)
|
||||||
|
event_add(u->ev_read, &timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_login_failure(struct hub_info* hub, struct user* u, enum status_message msg)
|
||||||
|
{
|
||||||
|
log_user_login_error(u, msg);
|
||||||
|
hub_send_status(hub, u, msg, status_level_fatal);
|
||||||
|
user_disconnect(u, quit_logon_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_nick_change(struct hub_info* hub, struct user* u, const char* nick)
|
||||||
|
{
|
||||||
|
if (user_is_logged_in(u))
|
||||||
|
{
|
||||||
|
log_user_nick_change(u, nick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_logout_user(struct hub_info* hub, struct user* user)
|
||||||
|
{
|
||||||
|
const char* reason = "";
|
||||||
|
|
||||||
|
/* These are used for logging purposes */
|
||||||
|
switch (user->quit_reason)
|
||||||
|
{
|
||||||
|
case quit_disconnected: reason = "disconnected"; break;
|
||||||
|
case quit_kicked: reason = "kicked"; break;
|
||||||
|
case quit_banned: reason = "banned"; break;
|
||||||
|
case quit_timeout: reason = "timeout"; break;
|
||||||
|
case quit_send_queue: reason = "send queue"; break;
|
||||||
|
case quit_memory_error: reason = "out of memory"; break;
|
||||||
|
case quit_socket_error: reason = "socket error"; break;
|
||||||
|
case quit_protocol_error: reason = "protocol error"; break;
|
||||||
|
case quit_logon_error: reason = "login error"; break;
|
||||||
|
case quit_hub_disabled: reason = "hub disabled"; break;
|
||||||
|
case quit_ghost_timeout: reason = "ghost"; break;
|
||||||
|
default:
|
||||||
|
if (hub->status == hub_status_shutdown)
|
||||||
|
reason = "hub shutdown";
|
||||||
|
else
|
||||||
|
reason = "unknown error";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_user_logout(user, reason);
|
||||||
|
user->quit_reason = 0;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -23,23 +23,22 @@
|
|||||||
/**
|
/**
|
||||||
* This event is triggered whenever a user successfully logs in to the hub.
|
* This event is triggered whenever a user successfully logs in to the hub.
|
||||||
*/
|
*/
|
||||||
extern void on_login_success(struct hub_info* hub, struct hub_user* u);
|
extern void on_login_success(struct hub_info* hub, struct user* u);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This event is triggered whenever a user failed to log in to the hub.
|
* This event is triggered whenever a user failed to log in to the hub.
|
||||||
*/
|
*/
|
||||||
extern void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg);
|
extern void on_login_failure(struct hub_info* hub, struct user* u, enum status_message msg);
|
||||||
extern void on_update_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This event is triggered whenever a previously logged in user leaves the hub.
|
* This event is triggered whenever a previously logged in user leaves the hub.
|
||||||
*/
|
*/
|
||||||
extern void on_logout_user(struct hub_info* hub, struct hub_user* u);
|
extern void on_logout_user(struct hub_info* hub, struct user* u);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This event is triggered whenever a user changes his/her nickname.
|
* This event is triggered whenever a user changes his/her nickname.
|
||||||
*/
|
*/
|
||||||
extern void on_nick_change(struct hub_info* hub, struct hub_user* u, const char* nick);
|
extern void on_nick_change(struct hub_info* hub, struct user* u, const char* nick);
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_HUB_EVENT_H */
|
#endif /* HAVE_UHUB_HUB_EVENT_H */
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -39,16 +39,15 @@ static void remove_server_restricted_flags(struct adc_message* cmd)
|
|||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_REFERER);
|
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_REFERER);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_feature_cast_supports(struct hub_user* u, struct adc_message* cmd)
|
static int user_is_protected(struct user* user);
|
||||||
|
|
||||||
|
static int set_feature_cast_supports(struct user* u, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
char *it, *tmp;
|
char *it, *tmp;
|
||||||
|
|
||||||
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_SUPPORT))
|
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_SUPPORT))
|
||||||
{
|
{
|
||||||
tmp = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SUPPORT);
|
tmp = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SUPPORT);
|
||||||
if (!tmp)
|
|
||||||
return -1; // FIXME: OOM
|
|
||||||
|
|
||||||
user_clear_feature_cast_support(u);
|
user_clear_feature_cast_support(u);
|
||||||
|
|
||||||
it = tmp;
|
it = tmp;
|
||||||
@@ -90,7 +89,7 @@ static int check_hash_tiger(const char* cid, const char* pid)
|
|||||||
/*
|
/*
|
||||||
* FIXME: Only works for tiger hash. If a client doesnt support tiger we cannot let it in!
|
* FIXME: Only works for tiger hash. If a client doesnt support tiger we cannot let it in!
|
||||||
*/
|
*/
|
||||||
static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
static int check_cid(struct hub_info* hub, struct user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
size_t pos;
|
size_t pos;
|
||||||
char* cid = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID);
|
char* cid = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID);
|
||||||
@@ -151,7 +150,7 @@ static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_mes
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int check_required_login_flags(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
static int check_required_login_flags(struct hub_info* hub, struct user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
|
||||||
@@ -187,15 +186,15 @@ static int check_required_login_flags(struct hub_info* hub, struct hub_user* use
|
|||||||
* remove any wrong address, and replace it with the correct one
|
* remove any wrong address, and replace it with the correct one
|
||||||
* as seen by the hub.
|
* as seen by the hub.
|
||||||
*/
|
*/
|
||||||
static int check_network(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
int check_network(struct hub_info* hub, struct user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
const char* address = user_get_address(user);
|
const char* address = ip_convert_to_string(&user->ipaddr);
|
||||||
|
|
||||||
/* Check for NAT override address */
|
/* Check for NAT override address */
|
||||||
if (acl_is_ip_nat_override(hub->acl, address))
|
if (acl_is_ip_nat_override(hub->acl, address))
|
||||||
{
|
{
|
||||||
char* client_given_ip = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
|
char* client_given_ip = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
|
||||||
if (client_given_ip && strcmp(client_given_ip, "0.0.0.0") != 0)
|
if (strcmp(client_given_ip, "0.0.0.0") != 0)
|
||||||
{
|
{
|
||||||
user_set_nat_override(user);
|
user_set_nat_override(user);
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
|
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
|
||||||
@@ -223,7 +222,7 @@ static int check_network(struct hub_info* hub, struct hub_user* user, struct adc
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void strip_network(struct hub_user* user, struct adc_message* cmd)
|
void strip_network(struct user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
|
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT);
|
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT);
|
||||||
@@ -277,7 +276,7 @@ static int nick_is_utf8(const char* nick)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int check_nick(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
static int check_nick(struct hub_info* hub, struct user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
char* nick;
|
char* nick;
|
||||||
char* tmp;
|
char* tmp;
|
||||||
@@ -325,10 +324,10 @@ static int check_nick(struct hub_info* hub, struct hub_user* user, struct adc_me
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int check_logged_in(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
static int check_logged_in(struct hub_info* hub, struct user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
struct hub_user* lookup1 = uman_get_user_by_nick(hub, user->id.nick);
|
struct user* lookup1 = uman_get_user_by_nick(hub, user->id.nick);
|
||||||
struct hub_user* lookup2 = uman_get_user_by_cid(hub, user->id.cid);
|
struct user* lookup2 = uman_get_user_by_cid(hub, user->id.cid);
|
||||||
|
|
||||||
if (lookup1 == user)
|
if (lookup1 == user)
|
||||||
{
|
{
|
||||||
@@ -339,20 +338,20 @@ static int check_logged_in(struct hub_info* hub, struct hub_user* user, struct a
|
|||||||
{
|
{
|
||||||
if (lookup1 == lookup2)
|
if (lookup1 == lookup2)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("check_logged_in: exact same user is logged in: %s", user->id.nick);
|
hub_log(log_debug, "check_logged_in: exact same user is logged in: %s", user->id.nick);
|
||||||
hub_disconnect_user(hub, lookup1, quit_ghost_timeout);
|
user_disconnect(lookup1, quit_ghost_timeout);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (lookup1)
|
if (lookup1)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("check_logged_in: nickname is in use: %s", user->id.nick);
|
hub_log(log_debug, "check_logged_in: nickname is in use: %s", user->id.nick);
|
||||||
return status_msg_inf_error_nick_taken;
|
return status_msg_inf_error_nick_taken;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_DEBUG("check_logged_in: CID is in use: %s", user->id.cid);
|
hub_log(log_debug, "check_logged_in: CID is in use: %s", user->id.cid);
|
||||||
return status_msg_inf_error_cid_taken;
|
return status_msg_inf_error_cid_taken;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -366,7 +365,7 @@ static int check_logged_in(struct hub_info* hub, struct hub_user* user, struct a
|
|||||||
* But this is not something we want to do, and is deprecated in the ADC specification.
|
* But this is not something we want to do, and is deprecated in the ADC specification.
|
||||||
* One should rather look at capabilities/features.
|
* One should rather look at capabilities/features.
|
||||||
*/
|
*/
|
||||||
static int check_user_agent(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
static int check_user_agent(struct hub_info* hub, struct user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
char* ua_encoded = 0;
|
char* ua_encoded = 0;
|
||||||
char* ua = 0;
|
char* ua = 0;
|
||||||
@@ -387,7 +386,7 @@ static int check_user_agent(struct hub_info* hub, struct hub_user* user, struct
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int check_acl(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
static int check_acl(struct hub_info* hub, struct user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
if (acl_is_cid_banned(hub->acl, user->id.cid))
|
if (acl_is_cid_banned(hub->acl, user->id.cid))
|
||||||
{
|
{
|
||||||
@@ -407,7 +406,7 @@ static int check_acl(struct hub_info* hub, struct hub_user* user, struct adc_mes
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
static int check_limits(struct hub_info* hub, struct user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
char* arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_SIZE);
|
char* arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_SIZE);
|
||||||
if (arg)
|
if (arg)
|
||||||
@@ -526,16 +525,17 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the expected credentials, and returns 1 if authentication is needed,
|
* Set the expected credentials, and returns 1 if authentication is needed,
|
||||||
* or 0 if not.
|
* or 0 if not.
|
||||||
* If the hub is configured to allow only registered users and the user
|
* If the hub is configured to allow only registered users and the user
|
||||||
* is not recognized this will return 1.
|
* is not recognized this will return 1.
|
||||||
*/
|
*/
|
||||||
static int set_credentials(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
static int set_credentials(struct hub_info* hub, struct user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct hub_user_access_info* info = acl_get_access_info(hub->acl, user->id.nick);
|
struct user_access_info* info = acl_get_access_info(hub->acl, user->id.nick);
|
||||||
|
|
||||||
if (info)
|
if (info)
|
||||||
{
|
{
|
||||||
@@ -584,8 +584,49 @@ static int set_credentials(struct hub_info* hub, struct hub_user* user, struct a
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a user is to be let into the hub even if the hub is "full".
|
||||||
|
*/
|
||||||
|
static int user_is_protected(struct user* user)
|
||||||
|
{
|
||||||
|
switch (user->credentials)
|
||||||
|
{
|
||||||
|
case cred_bot:
|
||||||
|
case cred_operator:
|
||||||
|
case cred_super:
|
||||||
|
case cred_admin:
|
||||||
|
case cred_link:
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int check_is_hub_full(struct hub_info* hub, struct hub_user* user)
|
/**
|
||||||
|
* Returns 1 if a user is registered.
|
||||||
|
* Only registered users will be let in if the hub is configured for registered
|
||||||
|
* users only.
|
||||||
|
*/
|
||||||
|
static int user_is_registered(struct user* user)
|
||||||
|
{
|
||||||
|
switch (user->credentials)
|
||||||
|
{
|
||||||
|
case cred_bot:
|
||||||
|
case cred_user:
|
||||||
|
case cred_operator:
|
||||||
|
case cred_super:
|
||||||
|
case cred_admin:
|
||||||
|
case cred_link:
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int check_is_hub_full(struct hub_info* hub, struct user* user)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* If hub is full, don't let users in, but we still want to allow
|
* If hub is full, don't let users in, but we still want to allow
|
||||||
@@ -599,7 +640,7 @@ static int check_is_hub_full(struct hub_info* hub, struct hub_user* user)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int check_registered_users_only(struct hub_info* hub, struct hub_user* user)
|
static int check_registered_users_only(struct hub_info* hub, struct user* user)
|
||||||
{
|
{
|
||||||
if (hub->config->registered_users_only && !user_is_registered(user))
|
if (hub->config->registered_users_only && !user_is_registered(user))
|
||||||
{
|
{
|
||||||
@@ -608,7 +649,7 @@ static int check_registered_users_only(struct hub_info* hub, struct hub_user* us
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hub_handle_info_common(struct hub_user* user, struct adc_message* cmd)
|
static int hub_handle_info_common(struct user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
/* Remove server restricted flags */
|
/* Remove server restricted flags */
|
||||||
remove_server_restricted_flags(cmd);
|
remove_server_restricted_flags(cmd);
|
||||||
@@ -619,7 +660,7 @@ static int hub_handle_info_common(struct hub_user* user, struct adc_message* cmd
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
if (hub->config->low_bandwidth_mode)
|
if (hub->config->low_bandwidth_mode)
|
||||||
{
|
{
|
||||||
@@ -647,7 +688,7 @@ static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct hub_user*
|
|||||||
return ret; \
|
return ret; \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
static int hub_perform_login_checks(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
int hub_perform_login_checks(struct hub_info* hub, struct user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
/* Make syntax checks. */
|
/* Make syntax checks. */
|
||||||
INF_CHECK(check_required_login_flags, hub, user, cmd);
|
INF_CHECK(check_required_login_flags, hub, user, cmd);
|
||||||
@@ -657,24 +698,21 @@ static int hub_perform_login_checks(struct hub_info* hub, struct hub_user* user,
|
|||||||
INF_CHECK(check_user_agent, hub, user, cmd);
|
INF_CHECK(check_user_agent, hub, user, cmd);
|
||||||
INF_CHECK(check_acl, hub, user, cmd);
|
INF_CHECK(check_acl, hub, user, cmd);
|
||||||
INF_CHECK(check_logged_in, hub, user, cmd);
|
INF_CHECK(check_logged_in, hub, user, cmd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int hub_handle_info_login(struct hub_info* hub, struct user* user, struct adc_message* cmd)
|
||||||
* Perform additional INF checks used at time of login.
|
|
||||||
*
|
|
||||||
* @return 0 if success, <0 if error, >0 if authentication needed.
|
|
||||||
*/
|
|
||||||
int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
|
||||||
{
|
{
|
||||||
int code = 0;
|
int need_auth = 0;
|
||||||
|
|
||||||
INF_CHECK(hub_perform_login_checks, hub, user, cmd);
|
INF_CHECK(hub_perform_login_checks, hub, user, cmd);
|
||||||
|
|
||||||
/* Private ID must never be broadcasted - drop it! */
|
/* Private ID must never be broadcasted - drop it! */
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
|
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
|
||||||
|
|
||||||
code = set_credentials(hub, user, cmd);
|
/* FIXME: This needs some cleaning up */
|
||||||
|
need_auth = set_credentials(hub, user, cmd);
|
||||||
|
|
||||||
/* Note: this must be done *after* set_credentials. */
|
/* Note: this must be done *after* set_credentials. */
|
||||||
if (check_is_hub_full(hub, user))
|
if (check_is_hub_full(hub, user))
|
||||||
@@ -695,7 +733,7 @@ int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct ad
|
|||||||
/* Set initial user info */
|
/* Set initial user info */
|
||||||
user_set_info(user, cmd);
|
user_set_info(user, cmd);
|
||||||
|
|
||||||
return code;
|
return need_auth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -711,9 +749,8 @@ int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct ad
|
|||||||
* - CID/PID (valid, not taken, etc).
|
* - CID/PID (valid, not taken, etc).
|
||||||
* - IP addresses (IPv4 and IPv6)
|
* - IP addresses (IPv4 and IPv6)
|
||||||
*/
|
*/
|
||||||
int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct adc_message* cmd_unmodified)
|
int hub_handle_info(struct hub_info* hub, struct user* user, const struct adc_message* cmd_unmodified)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
struct adc_message* cmd = adc_msg_copy(cmd_unmodified);
|
struct adc_message* cmd = adc_msg_copy(cmd_unmodified);
|
||||||
if (!cmd) return -1; /* OOM */
|
if (!cmd) return -1; /* OOM */
|
||||||
|
|
||||||
@@ -736,7 +773,7 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = hub_handle_info_login(hub, user, cmd);
|
int ret = hub_handle_info_login(hub, user, cmd);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
on_login_failure(hub, user, ret);
|
on_login_failure(hub, user, ret);
|
||||||
@@ -768,20 +805,14 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
|
|||||||
*/
|
*/
|
||||||
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_NICK))
|
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_NICK))
|
||||||
{
|
{
|
||||||
#ifdef ALLOW_CHANGE_NICK
|
#if ALLOW_CHANGE_NICK
|
||||||
if (!check_nick(hub, user, cmd))
|
if (!check_nick(hub, user, cmd))
|
||||||
#endif
|
#endif
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK);
|
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = check_limits(hub, user, cmd);
|
/* FIXME - What if limits are not met ? */
|
||||||
if (ret < 0)
|
check_limits(hub, user, cmd);
|
||||||
{
|
|
||||||
on_update_failure(hub, user, ret);
|
|
||||||
adc_msg_free(cmd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
strip_network(user, cmd);
|
strip_network(user, cmd);
|
||||||
hub_handle_info_low_bandwidth(hub, user, cmd);
|
hub_handle_info_low_bandwidth(hub, user, cmd);
|
||||||
|
|
||||||
@@ -789,7 +820,7 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
|
|||||||
|
|
||||||
if (!adc_msg_is_empty(cmd))
|
if (!adc_msg_is_empty(cmd))
|
||||||
{
|
{
|
||||||
route_message(hub, user, cmd);
|
route_message(user, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
adc_msg_free(cmd);
|
adc_msg_free(cmd);
|
||||||
@@ -797,5 +828,3 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -47,7 +47,7 @@ enum nick_status
|
|||||||
*
|
*
|
||||||
* @return 0 on success, -1 on error
|
* @return 0 on success, -1 on error
|
||||||
*/
|
*/
|
||||||
extern int hub_handle_info(struct hub_info* hub, struct hub_user* u, const struct adc_message* cmd);
|
extern int hub_handle_info(struct hub_info* hub, struct user* u, const struct adc_message* cmd);
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_INF_PARSER_H */
|
#endif /* HAVE_UHUB_INF_PARSER_H */
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
|
|
||||||
|
|
||||||
int ip_is_valid_ipv4(const char* address)
|
int ip_is_valid_ipv4(const char* address)
|
||||||
{
|
{
|
||||||
int i = 0; /* address index */
|
int i = 0; /* address index */
|
||||||
@@ -146,7 +147,7 @@ int ip_convert_address(const char* text_address, int port, struct sockaddr* addr
|
|||||||
addr6.sin6_port = htons(port);
|
addr6.sin6_port = htons(port);
|
||||||
if (net_string_to_address(AF_INET6, taddr, &addr6.sin6_addr) <= 0)
|
if (net_string_to_address(AF_INET6, taddr, &addr6.sin6_addr) <= 0)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Unable to convert socket address (ipv6)");
|
hub_log(log_fatal, "Unable to convert socket address (ipv6)");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +163,7 @@ int ip_convert_address(const char* text_address, int port, struct sockaddr* addr
|
|||||||
addr4.sin_port = htons(port);
|
addr4.sin_port = htons(port);
|
||||||
if (net_string_to_address(AF_INET, taddr, &addr4.sin_addr) <= 0)
|
if (net_string_to_address(AF_INET, taddr, &addr4.sin_addr) <= 0)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Unable to convert socket address (ipv4)");
|
hub_log(log_fatal, "Unable to convert socket address (ipv4)");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memcpy(addr, &addr4, sockaddr_size);
|
memcpy(addr, &addr4, sockaddr_size);
|
||||||
@@ -218,7 +219,7 @@ int ip_mask_create_left(int af, int bits, struct ip_addr_encap* result)
|
|||||||
|
|
||||||
#ifdef IP_CALC_DEBUG
|
#ifdef IP_CALC_DEBUG
|
||||||
char* r_str = hub_strdup(ip_convert_to_string(result));
|
char* r_str = hub_strdup(ip_convert_to_string(result));
|
||||||
LOG_DUMP("Created left mask: %s", r_str);
|
hub_log(log_debug, "Created left mask: %s", r_str);
|
||||||
hub_free(r_str);
|
hub_free(r_str);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -271,7 +272,7 @@ int ip_mask_create_right(int af, int bits, struct ip_addr_encap* result)
|
|||||||
|
|
||||||
#ifdef IP_CALC_DEBUG
|
#ifdef IP_CALC_DEBUG
|
||||||
char* r_str = hub_strdup(ip_convert_to_string(result));
|
char* r_str = hub_strdup(ip_convert_to_string(result));
|
||||||
LOG_DUMP("Created right mask: %s", r_str);
|
hub_log(log_debug, "Created right mask: %s", r_str);
|
||||||
hub_free(r_str);
|
hub_free(r_str);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -404,7 +405,7 @@ int ip_compare(struct ip_addr_encap* a, struct ip_addr_encap* b)
|
|||||||
#ifdef IP_CALC_DEBUG
|
#ifdef IP_CALC_DEBUG
|
||||||
char* a_str = hub_strdup(ip_convert_to_string(a));
|
char* a_str = hub_strdup(ip_convert_to_string(a));
|
||||||
char* b_str = hub_strdup(ip_convert_to_string(b));
|
char* b_str = hub_strdup(ip_convert_to_string(b));
|
||||||
LOG_DUMP("Comparing IPs '%s' AND '%s' => %d", a_str, b_str, ret);
|
hub_log(log_debug, "Comparing IPs '%s' AND '%s' => %d", a_str, b_str, ret);
|
||||||
hub_free(a_str);
|
hub_free(a_str);
|
||||||
hub_free(b_str);
|
hub_free(b_str);
|
||||||
#endif
|
#endif
|
||||||
@@ -412,81 +413,13 @@ int ip_compare(struct ip_addr_encap* a, struct ip_addr_encap* b)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_ip_mask(const char* text_addr, int bits, struct ip_range* range)
|
|
||||||
{
|
|
||||||
if (ip_is_valid_ipv4(text_addr) || ip_is_valid_ipv6(text_addr))
|
|
||||||
{
|
|
||||||
struct ip_addr_encap addr;
|
|
||||||
struct ip_addr_encap mask1;
|
|
||||||
struct ip_addr_encap mask2;
|
|
||||||
int af = ip_convert_to_binary(text_addr, &addr); /* 192.168.1.2 */
|
|
||||||
int maxbits = (af == AF_INET6 ? 128 : 32);
|
|
||||||
bits = MIN(MAX(bits, 0), maxbits);
|
|
||||||
ip_mask_create_left(af, bits, &mask1); /* 255.255.255.0 */
|
|
||||||
ip_mask_create_right(af, maxbits - bits, &mask2); /* 0.0.0.255 */
|
|
||||||
ip_mask_apply_AND(&addr, &mask1, &range->lo); /* 192.168.1.0 */
|
|
||||||
ip_mask_apply_OR(&range->lo, &mask2, &range->hi); /* 192.168.1.255 */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int check_ip_range(const char* lo, const char* hi, struct ip_range* range)
|
|
||||||
{
|
|
||||||
int ret1, ret2;
|
|
||||||
if ((ip_is_valid_ipv4(lo) && ip_is_valid_ipv4(hi)) || (ip_is_valid_ipv6(lo) && ip_is_valid_ipv6(hi)))
|
|
||||||
{
|
|
||||||
ret1 = ip_convert_to_binary(lo, &range->lo);
|
|
||||||
ret2 = ip_convert_to_binary(hi, &range->hi);
|
|
||||||
if (ret1 == -1 || ret2 == -1 || ret1 != ret2)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
split = strrchr(address, '/');
|
|
||||||
if (split)
|
|
||||||
{
|
|
||||||
int mask = uhub_atoi(split+1);
|
|
||||||
if (mask == 0 && split[1] != '0') return 0;
|
|
||||||
addr = hub_strndup(address, split - address);
|
|
||||||
ret = check_ip_mask(addr, mask, range);
|
|
||||||
hub_free(addr);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
split = strrchr(address, '-');
|
|
||||||
if (split)
|
|
||||||
{
|
|
||||||
addr = hub_strndup(address, split - address);
|
|
||||||
ret = check_ip_range(addr, split+1, range);
|
|
||||||
hub_free(addr);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ip_is_valid_ipv4(address) || ip_is_valid_ipv6(address))
|
|
||||||
{
|
|
||||||
if (ip_convert_to_binary(address, &range->lo) == -1)
|
|
||||||
return 0;
|
|
||||||
memcpy(&range->hi, &range->lo, sizeof(struct ip_addr_encap));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ip_in_range(struct ip_addr_encap* addr, struct ip_range* range)
|
|
||||||
{
|
|
||||||
return (addr->af == range->lo.af && ip_compare(&range->lo, addr) <= 0 && ip_compare(addr, &range->hi) <= 0);
|
|
||||||
}
|
|
||||||
@@ -33,57 +33,26 @@ struct ip_addr_encap {
|
|||||||
} internal_ip_data;
|
} internal_ip_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ip_range
|
|
||||||
{
|
|
||||||
struct ip_addr_encap lo;
|
|
||||||
struct ip_addr_encap hi;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern int ip_convert_to_binary(const char* text_addr, struct ip_addr_encap* raw);
|
extern int ip_convert_to_binary(const char* text_addr, struct ip_addr_encap* raw);
|
||||||
|
|
||||||
extern const char* ip_convert_to_string(struct ip_addr_encap* raw);
|
extern const char* ip_convert_to_string(struct ip_addr_encap* raw);
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a string on the form:
|
|
||||||
* ip-ip or ip/mask to an iprange.
|
|
||||||
*
|
|
||||||
* Note: both IPv4 and IPv6 addresses are valid, but if a range is given
|
|
||||||
* both addresses must be of the same address family.
|
|
||||||
*
|
|
||||||
* Valid examples of address
|
|
||||||
* IPv4:
|
|
||||||
* 192.168.2.1
|
|
||||||
* 192.168.0.0/16
|
|
||||||
* 192.168.0.0-192.168.255.255
|
|
||||||
*
|
|
||||||
* IPv6:
|
|
||||||
* 2001:4860:A005::68
|
|
||||||
* 2001:4860:A005::0/80
|
|
||||||
* 2001:4860:A005::0-2001:4860:A005:ffff:ffff:ffff:ffff:ffff
|
|
||||||
*
|
|
||||||
* @return 0 if invalid, 1 if OK
|
|
||||||
*/
|
|
||||||
extern int ip_convert_address_to_range(const char* address, struct ip_range* range);
|
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* @return 1 if addr is inside range, 0 otherwise
|
|
||||||
*/
|
|
||||||
extern int ip_in_range(struct ip_addr_encap* addr, struct ip_range* range);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return 1 if address is a valid IPv4 address in text notation
|
* @return 1 if address is a valid IPv4 address in text notation
|
||||||
* 0 if invalid
|
* 0 if invalid
|
||||||
*/
|
*/
|
||||||
extern int ip_is_valid_ipv4(const char* address);
|
extern int ip_is_valid_ipv4(const char* address);
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* @return 1 if address is a valid IPv6 address in text notation
|
* @return 1 if address is a valid IPv6 address in text notation
|
||||||
* 0 if invalid
|
* 0 if invalid
|
||||||
*/
|
*/
|
||||||
extern int ip_is_valid_ipv6(const char* address);
|
extern int ip_is_valid_ipv6(const char* address);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* This function converts an IP address in text_address to a binary
|
* This function converts an IP address in text_address to a binary
|
||||||
* struct sockaddr.
|
* struct sockaddr.
|
||||||
* This will auto-detect if the IP-address is IPv6 (and that is supported),
|
* This will auto-detect if the IP-address is IPv6 (and that is supported),
|
||||||
@@ -97,6 +66,7 @@ extern int ip_is_valid_ipv6(const char* address);
|
|||||||
*/
|
*/
|
||||||
extern int ip_convert_address(const char* text_address, int port, struct sockaddr* addr, socklen_t* addr_len);
|
extern int ip_convert_address(const char* text_address, int port, struct sockaddr* addr, socklen_t* addr_len);
|
||||||
|
|
||||||
|
|
||||||
extern int ip_mask_create_left(int af, int bits, struct ip_addr_encap* result);
|
extern int ip_mask_create_left(int af, int bits, struct ip_addr_encap* result);
|
||||||
extern int ip_mask_create_right(int af, int bits, struct ip_addr_encap* result);
|
extern int ip_mask_create_right(int af, int bits, struct ip_addr_encap* result);
|
||||||
|
|
||||||
@@ -54,11 +54,6 @@ void list_clear(struct linked_list* list, void (*free_handle)(void* ptr))
|
|||||||
void list_append(struct linked_list* list, void* data_ptr)
|
void list_append(struct linked_list* list, void* data_ptr)
|
||||||
{
|
{
|
||||||
struct node* new_node = (struct node*) hub_malloc_zero(sizeof(struct node));
|
struct node* new_node = (struct node*) hub_malloc_zero(sizeof(struct node));
|
||||||
if (!new_node)
|
|
||||||
{
|
|
||||||
LOG_FATAL("Unable to allocate memory");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
new_node->ptr = data_ptr;
|
new_node->ptr = data_ptr;
|
||||||
|
|
||||||
if (list->last)
|
if (list->last)
|
||||||
@@ -33,31 +33,6 @@ enum log_verbosity {
|
|||||||
log_protocol = 9,
|
log_protocol = 9,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LOG_FATAL(format, ...) hub_log(log_fatal, format, ## __VA_ARGS__)
|
|
||||||
#define LOG_ERROR(format, ...) hub_log(log_error, format, ## __VA_ARGS__)
|
|
||||||
#define LOG_WARN(format, ...) hub_log(log_warning, format, ## __VA_ARGS__)
|
|
||||||
#define LOG_USER(format, ...) hub_log(log_user, format, ## __VA_ARGS__)
|
|
||||||
#define LOG_INFO(format, ...) hub_log(log_info, format, ## __VA_ARGS__)
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
# define LOG_DEBUG(format, ...) hub_log(log_debug, format, ## __VA_ARGS__)
|
|
||||||
# define LOG_TRACE(format, ...) hub_log(log_trace, format, ## __VA_ARGS__)
|
|
||||||
#else
|
|
||||||
# define LOG_DEBUG(format, ...) do { } while(0)
|
|
||||||
# define LOG_TRACE(format, ...) do { } while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef LOWLEVEL_DEBUG
|
|
||||||
# define LOG_DUMP(format, ...) hub_log(log_dump, format, ## __VA_ARGS__)
|
|
||||||
# define LOG_MEMORY(format, ...) hub_log(log_memory, format, ## __VA_ARGS__)
|
|
||||||
# define LOG_PROTO(format, ...) hub_log(log_protocol, format, ## __VA_ARGS__)
|
|
||||||
#else
|
|
||||||
# define LOG_DUMP(format, ...) do { } while(0)
|
|
||||||
# define LOG_MEMORY(format, ...) do { } while(0)
|
|
||||||
# define LOG_PROTO(format, ...) do { } while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify a minimum log verbosity for what messages should
|
* Specify a minimum log verbosity for what messages should
|
||||||
* be printed in the log.
|
* be printed in the log.
|
||||||
@@ -29,25 +29,24 @@ static const char* arg_uid = 0;
|
|||||||
static const char* arg_gid = 0;
|
static const char* arg_gid = 0;
|
||||||
static const char* arg_config = 0;
|
static const char* arg_config = 0;
|
||||||
static const char* arg_log = 0;
|
static const char* arg_log = 0;
|
||||||
static const char* arg_pid = 0;
|
|
||||||
static int arg_log_syslog = 0;
|
static int arg_log_syslog = 0;
|
||||||
|
|
||||||
|
|
||||||
#if !defined(WIN32)
|
#ifndef WIN32
|
||||||
extern struct hub_info* g_hub;
|
void hub_handle_signal(int fd, short events, void* arg)
|
||||||
void hub_handle_signal(int sig)
|
|
||||||
{
|
{
|
||||||
struct hub_info* hub = g_hub;
|
struct hub_info* hub = (struct hub_info*) arg;
|
||||||
|
int signal = fd;
|
||||||
|
|
||||||
switch (sig)
|
switch (signal)
|
||||||
{
|
{
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
LOG_INFO("Interrupted. Shutting down...");
|
hub_log(log_info, "Interrupted. Shutting down...");
|
||||||
hub->status = hub_status_shutdown;
|
hub->status = hub_status_shutdown;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
LOG_INFO("Terminated. Shutting down...");
|
hub_log(log_info, "Terminated. Shutting down...");
|
||||||
hub->status = hub_status_shutdown;
|
hub->status = hub_status_shutdown;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -59,12 +58,13 @@ void hub_handle_signal(int sig)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_TRACE("hub_handle_signal(): caught unknown signal: %d", signal);
|
hub_log(log_trace, "hub_handle_signal(): caught unknown signal: %d", signal);
|
||||||
hub->status = hub_status_shutdown;
|
hub->status = hub_status_shutdown;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct event signal_events[10];
|
||||||
static int signals[] =
|
static int signals[] =
|
||||||
{
|
{
|
||||||
SIGINT, /* Interrupt the application */
|
SIGINT, /* Interrupt the application */
|
||||||
@@ -76,28 +76,28 @@ static int signals[] =
|
|||||||
|
|
||||||
void setup_signal_handlers(struct hub_info* hub)
|
void setup_signal_handlers(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
sigset_t sig_set;
|
int i = 0;
|
||||||
struct sigaction act;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
sigemptyset(&sig_set);
|
|
||||||
act.sa_mask = sig_set;
|
|
||||||
act.sa_flags = SA_ONSTACK | SA_RESTART;
|
|
||||||
act.sa_handler = hub_handle_signal;
|
|
||||||
|
|
||||||
for (i = 0; signals[i]; i++)
|
for (i = 0; signals[i]; i++)
|
||||||
{
|
{
|
||||||
if (sigaction(signals[i], &act, 0) != 0)
|
signal_set(&signal_events[i], signals[i], hub_handle_signal, hub);
|
||||||
|
event_base_set(hub->evbase, &signal_events[i]);
|
||||||
|
if (signal_add(&signal_events[i], NULL))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Error setting signal handler %d", signals[i]);
|
hub_log(log_error, "Error setting signal handler %d", signals[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void shutdown_signal_handlers(struct hub_info* hub)
|
void shutdown_signal_handlers(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0; signals[i]; i++)
|
||||||
|
{
|
||||||
|
signal_del(&signal_events[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* !WIN32 */
|
|
||||||
|
#endif /* WIN32 */
|
||||||
|
|
||||||
|
|
||||||
int main_loop()
|
int main_loop()
|
||||||
@@ -113,8 +113,8 @@ int main_loop()
|
|||||||
{
|
{
|
||||||
if (hub)
|
if (hub)
|
||||||
{
|
{
|
||||||
LOG_INFO("Reloading configuration files...");
|
hub_log(log_info, "Reloading configuration files...");
|
||||||
LOG_DEBUG("Hub status: %d", (int) hub->status);
|
hub_log(log_debug, "Hub status: %d", (int) hub->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read_config(arg_config, &configuration, !arg_have_config) == -1)
|
if (read_config(arg_config, &configuration, !arg_have_config) == -1)
|
||||||
@@ -133,7 +133,7 @@ int main_loop()
|
|||||||
hub = hub_start_service(&configuration);
|
hub = hub_start_service(&configuration);
|
||||||
if (!hub)
|
if (!hub)
|
||||||
return -1;
|
return -1;
|
||||||
#if !defined(WIN32)
|
#ifndef WIN32
|
||||||
setup_signal_handlers(hub);
|
setup_signal_handlers(hub);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -146,9 +146,9 @@ int main_loop()
|
|||||||
acl_shutdown(&acl);
|
acl_shutdown(&acl);
|
||||||
free_config(&configuration);
|
free_config(&configuration);
|
||||||
|
|
||||||
} while (hub->status == hub_status_restart);
|
} while(hub->status != hub_status_shutdown);
|
||||||
|
|
||||||
#if !defined(WIN32)
|
#ifndef WIN32
|
||||||
shutdown_signal_handlers(hub);
|
shutdown_signal_handlers(hub);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ int main_loop()
|
|||||||
hub_shutdown_service(hub);
|
hub_shutdown_service(hub);
|
||||||
}
|
}
|
||||||
|
|
||||||
net_destroy();
|
net_shutdown();
|
||||||
hub_log_shutdown();
|
hub_log_shutdown();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -190,8 +190,8 @@ int check_configuration(int dump)
|
|||||||
|
|
||||||
void print_version()
|
void print_version()
|
||||||
{
|
{
|
||||||
fprintf(stdout, PRODUCT_STRING "\n");
|
fprintf(stdout, "" PRODUCT " " VERSION " " PRODUCT_TITLE "\n");
|
||||||
fprintf(stdout, COPYRIGHT "\n"
|
fprintf(stdout, "Copyright (C) 2007-2009, Jan Vidar Krey <janvidar@extatic.org>\n"
|
||||||
"This is free software with ABSOLUTELY NO WARRANTY.\n\n");
|
"This is free software with ABSOLUTELY NO WARRANTY.\n\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
@@ -215,7 +215,6 @@ void print_usage(char* program)
|
|||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
" -u <user> Run as given user\n"
|
" -u <user> Run as given user\n"
|
||||||
" -g <group> Run with given group permissions\n"
|
" -g <group> Run with given group permissions\n"
|
||||||
" -p <file> Store pid in file (process id)\n"
|
|
||||||
#endif
|
#endif
|
||||||
" -V Show version number.\n"
|
" -V Show version number.\n"
|
||||||
);
|
);
|
||||||
@@ -227,7 +226,7 @@ void print_usage(char* program)
|
|||||||
void parse_command_line(int argc, char** argv)
|
void parse_command_line(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int opt;
|
int opt;
|
||||||
while ((opt = getopt(argc, argv, "vqfc:l:hu:g:VCsSLp:")) != -1)
|
while ((opt = getopt(argc, argv, "vqfc:l:hu:g:VCsSL")) != -1)
|
||||||
{
|
{
|
||||||
switch (opt)
|
switch (opt)
|
||||||
{
|
{
|
||||||
@@ -287,10 +286,6 @@ void parse_command_line(int argc, char** argv)
|
|||||||
arg_gid = optarg;
|
arg_gid = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
|
||||||
arg_pid = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print_usage(argv[0]);
|
print_usage(argv[0]);
|
||||||
break;
|
break;
|
||||||
@@ -334,15 +329,15 @@ int drop_privileges()
|
|||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
{
|
{
|
||||||
LOG_FATAL("Unable to determine group id, check group name.");
|
hub_log(log_fatal, "Unable to determine group id, check group name.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_TRACE("Setting group id %d (%s)", (int) perm_gid, arg_gid);
|
hub_log(log_trace, "Setting group id %d (%s)", (int) perm_gid, arg_gid);
|
||||||
ret = setgid(perm_gid);
|
ret = setgid(perm_gid);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
LOG_FATAL("Unable to change group id, permission denied.");
|
hub_log(log_fatal, "Unable to change group id, permission denied.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
gid_ok = 1;
|
gid_ok = 1;
|
||||||
@@ -367,58 +362,31 @@ int drop_privileges()
|
|||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
{
|
{
|
||||||
LOG_FATAL("Unable to determine user id, check user name.");
|
hub_log(log_fatal, "Unable to determine user id, check user name.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gid_ok) {
|
if (!gid_ok) {
|
||||||
LOG_TRACE("Setting group id %d (%s)", (int) perm_gid, arg_gid);
|
hub_log(log_trace, "Setting group id %d (%s)", (int) perm_gid, arg_gid);
|
||||||
ret = setgid(perm_gid);
|
ret = setgid(perm_gid);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
LOG_FATAL("Unable to change group id, permission denied.");
|
hub_log(log_fatal, "Unable to change group id, permission denied.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_TRACE("Setting user id %d (%s)", (int) perm_uid, arg_uid);
|
hub_log(log_trace, "Setting user id %d (%s)", (int) perm_uid, arg_uid);
|
||||||
ret = setuid(perm_uid);
|
ret = setuid(perm_uid);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
LOG_FATAL("Unable to change user id, permission denied.");
|
hub_log(log_fatal, "Unable to change user id, permission denied.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pidfile_create()
|
|
||||||
{
|
|
||||||
if (arg_pid)
|
|
||||||
{
|
|
||||||
FILE* pidfile = fopen(arg_pid, "w");
|
|
||||||
if (!pidfile)
|
|
||||||
{
|
|
||||||
LOG_FATAL("Unable to write pid file: %s\n", arg_pid);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(pidfile, "%d", (int) getpid());
|
|
||||||
fclose(pidfile);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pidfile_destroy()
|
|
||||||
{
|
|
||||||
if (arg_pid)
|
|
||||||
{
|
|
||||||
return unlink(arg_pid);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
|
|
||||||
|
|
||||||
@@ -439,40 +407,26 @@ int main(int argc, char** argv)
|
|||||||
ret = fork();
|
ret = fork();
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
LOG_FATAL("Unable to fork to background!");
|
hub_log(log_fatal, "Unable to fork to background!");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if (ret == 0)
|
else if (ret == 0)
|
||||||
{
|
{
|
||||||
/* child process - detatch from TTY */
|
/* child process */
|
||||||
fclose(stdin);
|
|
||||||
fclose(stdout);
|
|
||||||
fclose(stderr);
|
|
||||||
close(0);
|
|
||||||
close(1);
|
|
||||||
close(2);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* parent process */
|
/* parent process */
|
||||||
LOG_DEBUG("Forked to background\n");
|
hub_log(log_debug, "Forked to background\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pidfile_create() == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (drop_privileges() == -1)
|
if (drop_privileges() == -1)
|
||||||
return -1;
|
return -1;
|
||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
|
|
||||||
ret = main_loop();
|
ret = main_loop();
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
pidfile_destroy();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ void internal_debug_print_leaks()
|
|||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
size_t leak = 0;
|
size_t leak = 0;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
LOG_MEMORY("--- exit (allocs: %d, size: " PRINTF_SIZE_T ") ---", hub_alloc_count, hub_alloc_size);
|
hub_log(log_memory, "--- exit (allocs: %d, size: %zu) ---", hub_alloc_count, hub_alloc_size);
|
||||||
|
|
||||||
for (; n < UHUB_MAX_ALLOCS; n++)
|
for (; n < UHUB_MAX_ALLOCS; n++)
|
||||||
{
|
{
|
||||||
@@ -55,11 +55,11 @@ void internal_debug_print_leaks()
|
|||||||
{
|
{
|
||||||
leak += hub_allocs[n].size;
|
leak += hub_allocs[n].size;
|
||||||
count++;
|
count++;
|
||||||
LOG_MEMORY("leak %p size: " PRINTF_SIZE_T " (bt: %p %p)", hub_allocs[n].ptr, hub_allocs[n].size, hub_allocs[n].stack1, hub_allocs[n].stack2);
|
hub_log(log_memory, "leak %p size: %zu (bt: %p %p)", hub_allocs[n].ptr, hub_allocs[n].size, hub_allocs[n].stack1, hub_allocs[n].stack2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_MEMORY("--- done (allocs: %d, size: " PRINTF_SIZE_T ", peak: %d/" PRINTF_SIZE_T ", oom: " PRINTF_SIZE_T ") ---", count, leak, hub_alloc_peak_count, hub_alloc_peak_size, hub_alloc_oom);
|
hub_log(log_memory, "--- done (allocs: %d, size: %zu, peak: %d/%zu, oom: %zu) ---", count, leak, hub_alloc_peak_count, hub_alloc_peak_size, hub_alloc_oom);
|
||||||
}
|
}
|
||||||
#endif /* REALTIME_MALLOC_TRACKING */
|
#endif /* REALTIME_MALLOC_TRACKING */
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ void* internal_debug_mem_malloc(size_t size, const char* where)
|
|||||||
/* Make sure the malloc info struct is initialized */
|
/* Make sure the malloc info struct is initialized */
|
||||||
if (!hub_alloc_count)
|
if (!hub_alloc_count)
|
||||||
{
|
{
|
||||||
LOG_MEMORY("--- start ---");
|
hub_log(log_memory, "--- start ---");
|
||||||
for (n = 0; n < UHUB_MAX_ALLOCS; n++)
|
for (n = 0; n < UHUB_MAX_ALLOCS; n++)
|
||||||
{
|
{
|
||||||
hub_allocs[n].ptr = 0;
|
hub_allocs[n].ptr = 0;
|
||||||
@@ -107,14 +107,14 @@ void* internal_debug_mem_malloc(size_t size, const char* where)
|
|||||||
hub_alloc_peak_count = MAX(hub_alloc_count, hub_alloc_peak_count);
|
hub_alloc_peak_count = MAX(hub_alloc_count, hub_alloc_peak_count);
|
||||||
hub_alloc_peak_size = MAX(hub_alloc_size, hub_alloc_peak_size);
|
hub_alloc_peak_size = MAX(hub_alloc_size, hub_alloc_peak_size);
|
||||||
|
|
||||||
LOG_MEMORY("%s %p (%d bytes) (bt: %p %p) {allocs: %d, size: " PRINTF_SIZE_T "}", where, ptr, (int) size, hub_allocs[n].stack1, hub_allocs[n].stack2, hub_alloc_count, hub_alloc_size);
|
hub_log(log_memory, "%s %p (%d bytes) (bt: %p %p) {allocs: %d, size: %zu}", where, ptr, (int) size, hub_allocs[n].stack1, hub_allocs[n].stack2, hub_alloc_count, hub_alloc_size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_MEMORY("%s *** OOM for %d bytes", where, size);
|
hub_log(log_memory, "%s *** OOM for %d bytes", where, size);
|
||||||
hub_alloc_oom++;
|
hub_alloc_oom++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -141,7 +141,7 @@ void internal_debug_mem_free(void* ptr)
|
|||||||
hub_allocs[n].size = 0;
|
hub_allocs[n].size = 0;
|
||||||
hub_allocs[n].stack1 = 0;
|
hub_allocs[n].stack1 = 0;
|
||||||
hub_allocs[n].stack2 = 0;
|
hub_allocs[n].stack2 = 0;
|
||||||
LOG_MEMORY("free %p (bt: %p %p) {allocs: %d, size: " PRINTF_SIZE_T "}", ptr, stack1, stack2, hub_alloc_count, hub_alloc_size);
|
hub_log(log_memory, "free %p (bt: %p %p) {allocs: %d, size: %zu}", ptr, stack1, stack2, hub_alloc_count, hub_alloc_size);
|
||||||
malloc_slot = n;
|
malloc_slot = n;
|
||||||
free(ptr);
|
free(ptr);
|
||||||
return;
|
return;
|
||||||
@@ -150,7 +150,7 @@ void internal_debug_mem_free(void* ptr)
|
|||||||
|
|
||||||
malloc_slot = -1;
|
malloc_slot = -1;
|
||||||
abort();
|
abort();
|
||||||
LOG_MEMORY("free %p *** NOT ALLOCATED *** (bt: %p %p)", ptr, stack1, stack2);
|
hub_log(log_memory, "free %p *** NOT ALLOCATED *** (bt: %p %p)", ptr, stack1, stack2);
|
||||||
#else
|
#else
|
||||||
free(ptr);
|
free(ptr);
|
||||||
#endif /* REALTIME_MALLOC_TRACKING */
|
#endif /* REALTIME_MALLOC_TRACKING */
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -26,51 +26,17 @@
|
|||||||
uhub_assert(X->capacity); \
|
uhub_assert(X->capacity); \
|
||||||
uhub_assert(X->length); \
|
uhub_assert(X->length); \
|
||||||
uhub_assert(X->length <= X->capacity); \
|
uhub_assert(X->length <= X->capacity); \
|
||||||
uhub_assert(X->references > 0); \
|
uhub_assert(X->length == strlen(X->cache)); \
|
||||||
uhub_assert(X->length == strlen(X->cache));
|
uhub_assert(X->references >= 0);
|
||||||
#define ADC_MSG_NULL_ON_FREE
|
|
||||||
#else
|
#else
|
||||||
#define ADC_MSG_ASSERT(X) do { } while(0)
|
#define ADC_MSG_ASSERT(X) do { } while(0)
|
||||||
#endif /* DEBUG */
|
#endif
|
||||||
|
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
#undef msg_malloc
|
|
||||||
#undef msg_malloc_zero
|
|
||||||
#undef msg_free
|
|
||||||
|
|
||||||
static void* msg_malloc(size_t size)
|
|
||||||
{
|
|
||||||
void* ptr = valloc(size);
|
|
||||||
LOG_MEMORY("msg_malloc: %p %d", ptr, (int) size);
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void* msg_malloc_zero(size_t size)
|
|
||||||
{
|
|
||||||
void* ptr = msg_malloc(size);
|
|
||||||
memset(ptr, 0, size);
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void msg_free(void* ptr)
|
|
||||||
{
|
|
||||||
LOG_MEMORY("msg_free: %p", ptr);
|
|
||||||
hub_free(ptr);
|
|
||||||
}
|
|
||||||
#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)
|
struct adc_message* adc_msg_incref(struct adc_message* msg)
|
||||||
{
|
{
|
||||||
|
if (!msg) return 0;
|
||||||
#ifndef ADC_MESSAGE_INCREF
|
#ifndef ADC_MESSAGE_INCREF
|
||||||
msg->references++;
|
msg->references++;
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_protect(msg);
|
|
||||||
#endif
|
|
||||||
return msg;
|
return msg;
|
||||||
#else
|
#else
|
||||||
struct adc_message* copy = adc_msg_copy(msg);
|
struct adc_message* copy = adc_msg_copy(msg);
|
||||||
@@ -96,19 +62,18 @@ static int adc_msg_grow(struct adc_message* msg, size_t size)
|
|||||||
newsize += 2; /* termination */
|
newsize += 2; /* termination */
|
||||||
newsize += (newsize % sizeof(size_t)); /* alignment padding */
|
newsize += (newsize % sizeof(size_t)); /* alignment padding */
|
||||||
|
|
||||||
buf = msg_malloc_zero(newsize);
|
buf = hub_malloc_zero(newsize);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (msg->cache)
|
if (msg->cache)
|
||||||
{
|
{
|
||||||
memcpy(buf, msg->cache, msg->length);
|
memcpy(buf, msg->cache, msg->length);
|
||||||
msg_free(msg->cache);
|
hub_free(msg->cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg->cache = buf;
|
msg->cache = buf;
|
||||||
msg->capacity = newsize;
|
msg->capacity = newsize;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,17 +149,13 @@ void adc_msg_free(struct adc_message* msg)
|
|||||||
|
|
||||||
ADC_MSG_ASSERT(msg);
|
ADC_MSG_ASSERT(msg);
|
||||||
|
|
||||||
|
if (msg->references > 0)
|
||||||
|
{
|
||||||
msg->references--;
|
msg->references--;
|
||||||
|
|
||||||
if (msg->references == 0)
|
|
||||||
{
|
|
||||||
#ifdef ADC_MSG_NULL_ON_FREE
|
|
||||||
if (msg->cache)
|
|
||||||
{
|
|
||||||
*msg->cache = 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
else
|
||||||
msg_free(msg->cache);
|
{
|
||||||
|
hub_free(msg->cache);
|
||||||
|
|
||||||
if (msg->feature_cast_include)
|
if (msg->feature_cast_include)
|
||||||
{
|
{
|
||||||
@@ -210,7 +171,7 @@ void adc_msg_free(struct adc_message* msg)
|
|||||||
msg->feature_cast_exclude = 0;
|
msg->feature_cast_exclude = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg_free(msg);
|
hub_free(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +179,7 @@ void adc_msg_free(struct adc_message* msg)
|
|||||||
struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
char* tmp = 0;
|
char* tmp = 0;
|
||||||
struct adc_message* copy = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
|
struct adc_message* copy = (struct adc_message*) hub_malloc_zero(sizeof(struct adc_message));
|
||||||
if (!copy) return NULL; /* OOM */
|
if (!copy) return NULL; /* OOM */
|
||||||
|
|
||||||
ADC_MSG_ASSERT(cmd);
|
ADC_MSG_ASSERT(cmd);
|
||||||
@@ -231,7 +192,7 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
|||||||
copy->length = cmd->length;
|
copy->length = cmd->length;
|
||||||
copy->capacity = 0;
|
copy->capacity = 0;
|
||||||
copy->priority = cmd->priority;
|
copy->priority = cmd->priority;
|
||||||
copy->references = 1;
|
copy->references = 0;
|
||||||
copy->feature_cast_include = 0;
|
copy->feature_cast_include = 0;
|
||||||
copy->feature_cast_exclude = 0;
|
copy->feature_cast_exclude = 0;
|
||||||
|
|
||||||
@@ -274,7 +235,7 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct adc_message* adc_msg_parse_verify(struct hub_user* u, const char* line, size_t length)
|
struct adc_message* adc_msg_parse_verify(struct user* u, const char* line, size_t length)
|
||||||
{
|
{
|
||||||
struct adc_message* command = adc_msg_parse(line, length);
|
struct adc_message* command = adc_msg_parse(line, length);
|
||||||
|
|
||||||
@@ -283,7 +244,6 @@ struct adc_message* adc_msg_parse_verify(struct hub_user* u, const char* line, s
|
|||||||
|
|
||||||
if (command->source && (!u || command->source != u->id.sid))
|
if (command->source && (!u || command->source != u->id.sid))
|
||||||
{
|
{
|
||||||
LOG_DEBUG("Command does not match user's SID (command->source=%d, user->id.sid=%d)", command->source, (u ? u->id.sid : 0));
|
|
||||||
adc_msg_free(command);
|
adc_msg_free(command);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -294,7 +254,7 @@ struct adc_message* adc_msg_parse_verify(struct hub_user* u, const char* line, s
|
|||||||
|
|
||||||
struct adc_message* adc_msg_parse(const char* line, size_t length)
|
struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||||
{
|
{
|
||||||
struct adc_message* command = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
|
struct adc_message* command = (struct adc_message*) hub_malloc_zero(sizeof(struct adc_message));
|
||||||
char prefix = line[0];
|
char prefix = line[0];
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
char temp_sid[5];
|
char temp_sid[5];
|
||||||
@@ -307,8 +267,8 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
|
|
||||||
if (!is_printable_utf8(line, length))
|
if (!is_printable_utf8(line, length))
|
||||||
{
|
{
|
||||||
LOG_DEBUG("Dropped message with non-printable UTF-8 characters.");
|
hub_log(log_debug, "Dropped message with non-printable UTF-8 characters.");
|
||||||
msg_free(command);
|
hub_free(command);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,7 +279,7 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
|
|
||||||
if (!adc_msg_grow(command, length + need_terminate))
|
if (!adc_msg_grow(command, length + need_terminate))
|
||||||
{
|
{
|
||||||
msg_free(command);
|
hub_free(command);
|
||||||
return NULL; /* OOM */
|
return NULL; /* OOM */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,7 +292,6 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
|
|
||||||
command->cmd = FOURCC(line[0], line[1], line[2], line[3]);
|
command->cmd = FOURCC(line[0], line[1], line[2], line[3]);
|
||||||
command->priority = 0;
|
command->priority = 0;
|
||||||
command->references = 1;
|
|
||||||
|
|
||||||
switch (prefix)
|
switch (prefix)
|
||||||
{
|
{
|
||||||
@@ -392,8 +351,8 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
{
|
{
|
||||||
list_destroy(command->feature_cast_include);
|
list_destroy(command->feature_cast_include);
|
||||||
list_destroy(command->feature_cast_exclude);
|
list_destroy(command->feature_cast_exclude);
|
||||||
msg_free(command->cache);
|
hub_free(command->cache);
|
||||||
msg_free(command);
|
hub_free(command);
|
||||||
return NULL; /* OOM */
|
return NULL; /* OOM */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,6 +375,7 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
|
|
||||||
if (n == 10)
|
if (n == 10)
|
||||||
ok = 0;
|
ok = 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'D':
|
case 'D':
|
||||||
@@ -482,19 +442,21 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ADC_MSG_ASSERT(command);
|
ADC_MSG_ASSERT(command);
|
||||||
|
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct adc_message* adc_msg_create(const char* line)
|
struct adc_message* adc_msg_create(const char* line)
|
||||||
{
|
{
|
||||||
return adc_msg_parse(line, strlen(line));
|
return adc_msg_parse_verify(NULL, line, strlen(line));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
||||||
{
|
{
|
||||||
struct adc_message* msg = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
|
struct adc_message* msg = (struct adc_message*) hub_malloc_zero(sizeof(struct adc_message));
|
||||||
|
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return NULL; /* OOM */
|
return NULL; /* OOM */
|
||||||
|
|
||||||
@@ -502,7 +464,7 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
|||||||
|
|
||||||
if (!adc_msg_grow(msg, size+1))
|
if (!adc_msg_grow(msg, size+1))
|
||||||
{
|
{
|
||||||
msg_free(msg);
|
hub_free(msg);
|
||||||
return NULL; /* OOM */
|
return NULL; /* OOM */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,7 +483,7 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
|||||||
|
|
||||||
msg->cmd = fourcc;
|
msg->cmd = fourcc;
|
||||||
msg->priority = 0;
|
msg->priority = 0;
|
||||||
msg->references = 1;
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -557,6 +519,7 @@ int adc_msg_remove_named_argument(struct adc_message* cmd, const char prefix_[2]
|
|||||||
{
|
{
|
||||||
|
|
||||||
temp_len = &end[0] - &start[0]; // strlen(start);
|
temp_len = &end[0] - &start[0]; // strlen(start);
|
||||||
|
/* hub_log(log_trace, " length=%d", (int) (temp_len)); */
|
||||||
endlen = strlen(end);
|
endlen = strlen(end);
|
||||||
|
|
||||||
memmove(start, end, endlen);
|
memmove(start, end, endlen);
|
||||||
@@ -691,27 +654,6 @@ int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], co
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int adc_msg_add_named_argument_string(struct adc_message* cmd, const char prefix[2], const char* string)
|
|
||||||
{
|
|
||||||
char* escaped = adc_msg_escape(string);
|
|
||||||
int ret = adc_msg_add_named_argument(cmd, prefix, escaped);
|
|
||||||
hub_free(escaped);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int adc_msg_add_named_argument_int(struct adc_message* cmd, const char prefix[2], int num)
|
|
||||||
{
|
|
||||||
const char* s = uhub_itoa(num);
|
|
||||||
int ret = adc_msg_add_named_argument(cmd, prefix, s);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int adc_msg_add_named_argument_uint64(struct adc_message* cmd, const char prefix[2], uint64_t num)
|
|
||||||
{
|
|
||||||
const char* s = uhub_ulltoa(num);
|
|
||||||
int ret = adc_msg_add_named_argument(cmd, prefix, s);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int adc_msg_add_argument(struct adc_message* cmd, const char* string)
|
int adc_msg_add_argument(struct adc_message* cmd, const char* string)
|
||||||
{
|
{
|
||||||
@@ -740,6 +682,7 @@ char* adc_msg_get_argument(struct adc_message* cmd, int offset)
|
|||||||
while (start)
|
while (start)
|
||||||
{
|
{
|
||||||
end = strchr(&start[1], ' ');
|
end = strchr(&start[1], ' ');
|
||||||
|
|
||||||
if (count == offset)
|
if (count == offset)
|
||||||
{
|
{
|
||||||
if (end)
|
if (end)
|
||||||
@@ -749,23 +692,17 @@ char* adc_msg_get_argument(struct adc_message* cmd, int offset)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
argument = hub_strdup(&start[1]);
|
argument = hub_strdup(&start[1]);
|
||||||
if (argument && argument[strlen(argument)-1] == '\n')
|
if (argument[strlen(argument)-1] == '\n')
|
||||||
argument[strlen(argument)-1] = 0;
|
argument[strlen(argument)-1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!argument)
|
|
||||||
return 0; // FIXME: OOM
|
|
||||||
|
|
||||||
if (*argument)
|
if (*argument)
|
||||||
{
|
{
|
||||||
adc_msg_terminate(cmd);
|
adc_msg_terminate(cmd);
|
||||||
return argument;
|
return argument;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
hub_free(argument);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
start = end;
|
start = end;
|
||||||
}
|
}
|
||||||
@@ -839,9 +776,12 @@ int adc_msg_unescape_length(const char* str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char* adc_msg_unescape(const char* string)
|
char* adc_msg_unescape(const char* string)
|
||||||
{
|
{
|
||||||
char* new_string = msg_malloc(adc_msg_unescape_length(string)+1);
|
char* new_string = hub_malloc(adc_msg_unescape_length(string)+1);
|
||||||
char* ptr = (char*) new_string;
|
char* ptr = (char*) new_string;
|
||||||
char* str = (char*) string;
|
char* str = (char*) string;
|
||||||
int escaped = 0;
|
int escaped = 0;
|
||||||
@@ -857,12 +797,14 @@ char* adc_msg_unescape(const char* string)
|
|||||||
*ptr++ = '\n';
|
*ptr++ = '\n';
|
||||||
else
|
else
|
||||||
*ptr++ = *str;
|
*ptr++ = *str;
|
||||||
|
|
||||||
escaped = 0;
|
escaped = 0;
|
||||||
} else {
|
} else {
|
||||||
if (*str == '\\')
|
if (*str == '\\')
|
||||||
escaped = 1;
|
escaped = 1;
|
||||||
else
|
else
|
||||||
*ptr++ = *str;
|
*ptr++ = *str;
|
||||||
|
|
||||||
}
|
}
|
||||||
str++;
|
str++;
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#ifndef HAVE_UHUB_COMMAND_H
|
#ifndef HAVE_UHUB_COMMAND_H
|
||||||
#define HAVE_UHUB_COMMAND_H
|
#define HAVE_UHUB_COMMAND_H
|
||||||
|
|
||||||
struct hub_user;
|
struct user;
|
||||||
|
|
||||||
struct adc_message
|
struct adc_message
|
||||||
{
|
{
|
||||||
@@ -70,7 +70,7 @@ extern struct adc_message* adc_msg_copy(const struct adc_message* cmd);
|
|||||||
* The message is only considered valid if the user who sent it
|
* The message is only considered valid if the user who sent it
|
||||||
* is the rightful origin of the message.
|
* is the rightful origin of the message.
|
||||||
*/
|
*/
|
||||||
extern struct adc_message* adc_msg_parse_verify(struct hub_user* u, const char* string, size_t length);
|
extern struct adc_message* adc_msg_parse_verify(struct user* u, const char* string, size_t length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will parse 'string' and return it as a adc_message struct, or
|
* This will parse 'string' and return it as a adc_message struct, or
|
||||||
@@ -173,22 +173,6 @@ extern int adc_msg_add_argument(struct adc_message* cmd, const char* string);
|
|||||||
*/
|
*/
|
||||||
extern int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
|
extern int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a string as a named argument.
|
|
||||||
* The string will automatcally be escaped, if you do not wish to escape th string use adc_msg_add_named_argument() instead.
|
|
||||||
*
|
|
||||||
* @arg prefix a 2 character argument prefix
|
|
||||||
* @arg string must NOT be escaped
|
|
||||||
* @return 0 if successful, or -1 if an error occured (out of memory).
|
|
||||||
*/
|
|
||||||
extern int adc_msg_add_named_argument_string(struct adc_message* cmd, const char prefix[2], const char* string);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append an integer as a named argument.
|
|
||||||
*/
|
|
||||||
extern int adc_msg_add_named_argument_int(struct adc_message* cmd, const char prefix[2], int integer);
|
|
||||||
extern int adc_msg_add_named_argument_uint64(struct adc_message* cmd, const char prefix[2], uint64_t num);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a ADC command escaped string to a regular string.
|
* Convert a ADC command escaped string to a regular string.
|
||||||
* @return string or NULL if out of memory
|
* @return string or NULL if out of memory
|
||||||
@@ -46,13 +46,10 @@ char* strip_white_space(char* string)
|
|||||||
{
|
{
|
||||||
char* pos;
|
char* pos;
|
||||||
|
|
||||||
if (!string)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
while (string[0] && is_white_space(string[0])) string++;
|
while (string[0] && is_white_space(string[0])) string++;
|
||||||
|
|
||||||
if (!*string)
|
if (!*string)
|
||||||
return string;
|
return 0;
|
||||||
|
|
||||||
/* Strip appending whitespace */
|
/* Strip appending whitespace */
|
||||||
pos = &string[strlen(string)-1];
|
pos = &string[strlen(string)-1];
|
||||||
@@ -171,96 +168,67 @@ void base32_decode(const char* src, unsigned char* dst, size_t len) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int string_split(const char* string, const char* split, void* data, string_split_handler_t handler)
|
|
||||||
{
|
|
||||||
char* buf = strdup(string);
|
|
||||||
char* start;
|
|
||||||
char* pos;
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
start = buf;
|
|
||||||
while ((pos = strstr(start, split)))
|
|
||||||
{
|
|
||||||
pos[0] = '\0';
|
|
||||||
start = strip_white_space(start);
|
|
||||||
if (*start)
|
|
||||||
{
|
|
||||||
if (handler(start, count, data) < 0)
|
|
||||||
{
|
|
||||||
hub_free(buf);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
start = &pos[1];
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
start = strip_white_space(start);
|
|
||||||
if (*start)
|
|
||||||
{
|
|
||||||
if (handler(start, count, data) < 0)
|
|
||||||
{
|
|
||||||
hub_free(buf);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hub_free(buf);
|
|
||||||
return count+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct file_read_line_data
|
|
||||||
{
|
|
||||||
file_line_handler_t handler;
|
|
||||||
void* data;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int file_read_line_handler(char* line, int count, void* ptr)
|
|
||||||
{
|
|
||||||
struct file_read_line_data* data = (struct file_read_line_data*) ptr;
|
|
||||||
|
|
||||||
LOG_DUMP("Line: %s", line);
|
|
||||||
if (data->handler(line, count+1, data->data) < 0)
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int file_read_lines(const char* file, void* data, file_line_handler_t handler)
|
int file_read_lines(const char* file, void* data, file_line_handler_t handler)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
char buf[MAX_RECV_BUF];
|
char buf[MAX_RECV_BUF];
|
||||||
struct file_read_line_data split_data;
|
char *pos, *start;
|
||||||
|
size_t line_count = 0;
|
||||||
|
|
||||||
memset(buf, 0, MAX_RECV_BUF);
|
memset(buf, 0, MAX_RECV_BUF);
|
||||||
|
|
||||||
LOG_TRACE("Opening file %s for line reading.", file);
|
hub_log(log_trace, "Opening file %s for line reading.", file);
|
||||||
|
|
||||||
fd = open(file, 0);
|
fd = open(file, 0);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Unable to open file %s: %s", file, strerror(errno));
|
hub_log(log_error, "Unable to open file %s: %s", file, strerror(errno));
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = read(fd, buf, MAX_RECV_BUF);
|
ret = read(fd, buf, MAX_RECV_BUF);
|
||||||
close(fd);
|
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Unable to read from file %s: %s", file, strerror(errno));
|
hub_log(log_error, "Unable to read from file %s: %s", file, strerror(errno));
|
||||||
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if (ret == 0)
|
else if (ret == 0)
|
||||||
{
|
{
|
||||||
LOG_WARN("File is empty.");
|
close(fd);
|
||||||
|
hub_log(log_warning, "File is empty.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
|
||||||
/* Parse configuaration */
|
/* Parse configuaration */
|
||||||
split_data.handler = handler;
|
start = buf;
|
||||||
split_data.data = data;
|
while ((pos = strchr(start, '\n')))
|
||||||
|
{
|
||||||
|
pos[0] = '\0';
|
||||||
|
if (*start)
|
||||||
|
{
|
||||||
|
hub_log(log_dump, "Line: %s", start);
|
||||||
|
if (handler(start, line_count+1, data) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
start = &pos[1];
|
||||||
|
line_count++;
|
||||||
|
}
|
||||||
|
|
||||||
return string_split(buf, "\n", &split_data, file_read_line_handler);
|
if (*start)
|
||||||
|
{
|
||||||
|
buf[strlen(start)] = 0;
|
||||||
|
hub_log(log_dump, "Line: %s", start);
|
||||||
|
if (handler(start, line_count+1, data) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return line_count+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -351,52 +319,4 @@ void* memmem(const void *haystack, size_t haystacklen, const void *needle, size_
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int split_string(const char* string, const char* split, struct linked_list* list, int allow_empty)
|
|
||||||
{
|
|
||||||
char* tmp1, *tmp2;
|
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
if (!string || !*string || !split || !*split || !list)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
tmp1 = strstr(string, split);
|
|
||||||
|
|
||||||
if (tmp1) tmp2 = hub_strndup(string, tmp1 - string);
|
|
||||||
else tmp2 = hub_strdup(string);
|
|
||||||
|
|
||||||
if (!tmp2)
|
|
||||||
{
|
|
||||||
list_clear(list, &hub_free);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*tmp2 || allow_empty)
|
|
||||||
{
|
|
||||||
/* store in list */
|
|
||||||
list_append(list, tmp2);
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* ignore element */
|
|
||||||
hub_free(tmp2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tmp1) break; /* last element found */
|
|
||||||
|
|
||||||
string = tmp1;
|
|
||||||
string += strlen(split);
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* get_timestamp(time_t now)
|
|
||||||
{
|
|
||||||
static char ts[32] = {0, };
|
|
||||||
struct tm* t = localtime(&now);
|
|
||||||
sprintf(ts, "[%02d:%02d]", t->tm_hour, t->tm_min);
|
|
||||||
return ts;
|
|
||||||
}
|
|
||||||
@@ -22,8 +22,6 @@
|
|||||||
|
|
||||||
typedef int (*file_line_handler_t)(char* line, int line_number, void* data);
|
typedef int (*file_line_handler_t)(char* line, int line_number, void* data);
|
||||||
|
|
||||||
extern const char* get_timestamp(time_t time);
|
|
||||||
|
|
||||||
extern int is_num(char c);
|
extern int is_num(char c);
|
||||||
extern int is_space(char c);
|
extern int is_space(char c);
|
||||||
extern int is_white_space(char c);
|
extern int is_white_space(char c);
|
||||||
@@ -55,15 +53,6 @@ extern char* strndup(const char* string, size_t n);
|
|||||||
void* memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);
|
void* memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* Split the string based on split, and place the different parts into list.
|
|
||||||
* @return the number of items in the list after split, or -1 if an error occured.
|
|
||||||
*/
|
|
||||||
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 */
|
#endif /* HAVE_UHUB_MISC_H */
|
||||||
|
|
||||||
319
src/netevent.c
Normal file
319
src/netevent.c
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
|
||||||
|
void net_on_read(int fd, short ev, void *arg)
|
||||||
|
{
|
||||||
|
static char buf[MAX_RECV_BUF];
|
||||||
|
struct user* user = (struct user*) arg;
|
||||||
|
char* pos;
|
||||||
|
size_t offset;
|
||||||
|
size_t buflen;
|
||||||
|
ssize_t size;
|
||||||
|
int more = 1;
|
||||||
|
int flag_close = 0;
|
||||||
|
|
||||||
|
hub_log(log_trace, "net_on_read() : fd=%d, ev=%d, arg=%p", fd, (int) ev, arg);
|
||||||
|
|
||||||
|
if (ev == EV_TIMEOUT)
|
||||||
|
{
|
||||||
|
more = 0;
|
||||||
|
if (user_is_connecting(user))
|
||||||
|
{
|
||||||
|
flag_close = quit_timeout;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// FIXME: hub is not neccesarily set!
|
||||||
|
// hub_send_ping(hub, user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (more)
|
||||||
|
{
|
||||||
|
offset = 0;
|
||||||
|
if (user->recv_buf)
|
||||||
|
{
|
||||||
|
memcpy(buf, user->recv_buf, user->recv_buf_offset);
|
||||||
|
offset = user->recv_buf_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = net_recv(fd, &buf[offset], MAX_RECV_BUF - offset, 0);
|
||||||
|
if (size == -1)
|
||||||
|
{
|
||||||
|
if (net_error() != EWOULDBLOCK)
|
||||||
|
flag_close = quit_socket_error;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (size == 0)
|
||||||
|
{
|
||||||
|
flag_close = quit_disconnected;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buflen = offset + size;
|
||||||
|
ssize_t handled = 0;
|
||||||
|
|
||||||
|
while ((pos = memchr(&buf[handled], '\n', (buflen - handled))))
|
||||||
|
{
|
||||||
|
pos[0] = '\0';
|
||||||
|
size_t msglen = &pos[0] - &buf[handled];
|
||||||
|
|
||||||
|
if (user_flag_get(user, flag_maxbuf))
|
||||||
|
{
|
||||||
|
user_flag_unset(user, flag_maxbuf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (msglen < user->hub->config->max_recv_buffer)
|
||||||
|
{
|
||||||
|
// FIXME: hub is not set????
|
||||||
|
if (hub_handle_message(user->hub, user, &buf[handled], msglen) == -1)
|
||||||
|
{
|
||||||
|
flag_close = quit_protocol_error;
|
||||||
|
more = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handled += msglen;
|
||||||
|
handled++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handled == 0 && user_flag_get(user, flag_maxbuf))
|
||||||
|
handled = buflen;
|
||||||
|
|
||||||
|
if (!more)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (handled < buflen)
|
||||||
|
{
|
||||||
|
if ((buflen - handled) > user->hub->config->max_recv_buffer)
|
||||||
|
{
|
||||||
|
user_flag_set(user, flag_maxbuf);
|
||||||
|
hub_free(user->recv_buf);
|
||||||
|
user->recv_buf = 0;
|
||||||
|
user->recv_buf_offset = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!user->recv_buf)
|
||||||
|
user->recv_buf = hub_malloc(user->hub->config->max_recv_buffer);
|
||||||
|
|
||||||
|
if (user->recv_buf)
|
||||||
|
{
|
||||||
|
memcpy(user->recv_buf, &buf[handled], buflen - handled);
|
||||||
|
user->recv_buf_offset = buflen - handled;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flag_close = quit_memory_error;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (user->recv_buf)
|
||||||
|
{
|
||||||
|
hub_free(user->recv_buf);
|
||||||
|
user->recv_buf = 0;
|
||||||
|
user->recv_buf_offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag_close)
|
||||||
|
{
|
||||||
|
user_disconnect(user, flag_close);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user_is_logged_in(user))
|
||||||
|
{
|
||||||
|
if (user->ev_read)
|
||||||
|
{
|
||||||
|
struct timeval timeout = { TIMEOUT_IDLE, 0 };
|
||||||
|
event_add(user->ev_read, &timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (user_is_connecting(user))
|
||||||
|
{
|
||||||
|
if (user->ev_read)
|
||||||
|
{
|
||||||
|
struct timeval timeout = { TIMEOUT_HANDSHAKE, 0 };
|
||||||
|
event_add(user->ev_read, &timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void net_on_write(int fd, short ev, void *arg)
|
||||||
|
{
|
||||||
|
struct user* user = (struct user*) arg;
|
||||||
|
struct adc_message* msg;
|
||||||
|
int ret;
|
||||||
|
int length;
|
||||||
|
int close_flag = 0;
|
||||||
|
|
||||||
|
msg = list_get_first(user->send_queue);
|
||||||
|
while (msg)
|
||||||
|
{
|
||||||
|
length = msg->length - user->send_queue_offset;
|
||||||
|
ret = net_send(user->sd, &msg->cache[user->send_queue_offset], length, UHUB_SEND_SIGNAL);
|
||||||
|
|
||||||
|
if (ret == 0 || (ret == -1 && net_error() == EWOULDBLOCK))
|
||||||
|
{
|
||||||
|
close_flag = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (ret > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
user->tm_last_write = time(NULL);
|
||||||
|
|
||||||
|
if (ret == length)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_SENDQ
|
||||||
|
hub_log(log_error, "SENDQ: sent=%d bytes/%d (all), send_queue_size=%d, offset=%d", ret, (int) msg->length, user->send_queue_size, user->send_queue_offset);
|
||||||
|
#endif
|
||||||
|
user->send_queue_size -= ret;
|
||||||
|
user->send_queue_offset = 0;
|
||||||
|
|
||||||
|
#ifdef DEBUG_SENDQ
|
||||||
|
if ((user->send_queue_size < 0) || (user->send_queue_offset < 0))
|
||||||
|
{
|
||||||
|
hub_log(log_error, "INVALID: send_queue_size=%d, send_queue_offset=%d", user->send_queue_size, user->send_queue_offset);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
list_remove(user->send_queue, msg);
|
||||||
|
|
||||||
|
if (user_flag_get(user, flag_user_list) && (msg == user->info || user->send_queue_size == 0))
|
||||||
|
{
|
||||||
|
user_flag_unset(user, flag_user_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
adc_msg_free(msg);
|
||||||
|
msg = 0;
|
||||||
|
|
||||||
|
if (user->send_queue_size == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_SENDQ
|
||||||
|
hub_log(log_error, "SENDQ: sent=%d bytes/%d (part), send_queue_size=%d, offset=%d", ret, (int) msg->length, user->send_queue_size, user->send_queue_offset);
|
||||||
|
#endif
|
||||||
|
user->send_queue_size -= ret;
|
||||||
|
user->send_queue_offset += ret;
|
||||||
|
|
||||||
|
#ifdef DEBUG_SENDQ
|
||||||
|
if ((user->send_queue_size < 0) || (user->send_queue_offset < 0) || (user->send_queue_offset > msg->length))
|
||||||
|
{
|
||||||
|
hub_log(log_error, "INVALID: send_queue_size=%d, send_queue_offset=%d", user->send_queue_size, user->send_queue_offset);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
close_flag = quit_socket_error;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
msg = list_get_first(user->send_queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (close_flag)
|
||||||
|
{
|
||||||
|
user_disconnect(user, close_flag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (user->send_queue_size > 0 && user->ev_write)
|
||||||
|
event_add(user->ev_write, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void net_on_accept(int server_fd, short ev, void *arg)
|
||||||
|
{
|
||||||
|
struct hub_info* hub = (struct hub_info*) arg;
|
||||||
|
struct user* user = 0;
|
||||||
|
struct ip_addr_encap ipaddr;
|
||||||
|
const char* addr;
|
||||||
|
struct timeval timeout = { TIMEOUT_CONNECTED, 0 };
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int fd = net_accept(server_fd, &ipaddr);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
if (net_error() == EWOULDBLOCK)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hub_log(log_error, "Accept error: %d %s", net_error(), strerror(net_error()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = ip_convert_to_string(&ipaddr);
|
||||||
|
|
||||||
|
/* FIXME: Should have a plugin log this */
|
||||||
|
hub_log(log_trace, "Got connection from %s", addr);
|
||||||
|
|
||||||
|
/* FIXME: A plugin should perform this check: is IP banned? */
|
||||||
|
if (acl_is_ip_banned(hub->acl, addr))
|
||||||
|
{
|
||||||
|
hub_log(log_info, "Denied [%s] (IP banned)", addr);
|
||||||
|
net_close(fd);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
user = user_create(hub, fd);
|
||||||
|
if (!user)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "Unable to create user after socket accepted. Out of memory?");
|
||||||
|
net_close(fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store IP address in user object */
|
||||||
|
memcpy(&user->ipaddr, &ipaddr, sizeof(ipaddr));
|
||||||
|
|
||||||
|
net_set_nonblocking(fd, 1);
|
||||||
|
net_set_nosigpipe(fd, 1);
|
||||||
|
|
||||||
|
event_set(user->ev_read, fd, EV_READ | EV_PERSIST, net_on_read, user);
|
||||||
|
event_set(user->ev_write, fd, EV_WRITE, net_on_write, user);
|
||||||
|
event_base_set(hub->evbase, user->ev_read);
|
||||||
|
event_base_set(hub->evbase, user->ev_write);
|
||||||
|
event_add(user->ev_read, &timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -20,15 +20,25 @@
|
|||||||
#ifndef HAVE_UHUB_NET_EVENT_H
|
#ifndef HAVE_UHUB_NET_EVENT_H
|
||||||
#define HAVE_UHUB_NET_EVENT_H
|
#define HAVE_UHUB_NET_EVENT_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Network callback for reading data from a socket.
|
||||||
|
*/
|
||||||
|
extern void net_on_read(int fd, short ev, void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Network callback for writing data to a socket.
|
||||||
|
*/
|
||||||
|
extern void net_on_write(int fd, short ev, void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Network callback for timers.
|
||||||
|
*/
|
||||||
|
extern void net_on_read_timeout(int fd, short ev, void* arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Network callback to accept incoming connections.
|
* Network callback to accept incoming connections.
|
||||||
*/
|
*/
|
||||||
extern void net_on_accept(struct net_connection* con, int event, void *arg);
|
extern void net_on_accept(int fd, short ev, void *arg);
|
||||||
extern void net_event(struct net_connection* con, int event, void *arg);
|
|
||||||
|
|
||||||
extern int handle_net_read(struct hub_user* user);
|
|
||||||
extern int handle_net_write(struct hub_user* user);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_NET_EVENT_H */
|
#endif /* HAVE_UHUB_NET_EVENT_H */
|
||||||
|
|
||||||
326
src/network-epoll.c
Normal file
326
src/network-epoll.c
Normal file
@@ -0,0 +1,326 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007, 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 HAVE_EPOLL
|
||||||
|
|
||||||
|
// #define DEBUG_EPOLL
|
||||||
|
static struct epoll_event* events = 0;
|
||||||
|
static int epfd = -1;
|
||||||
|
|
||||||
|
#ifdef DEBUG_EPOLL
|
||||||
|
static void dump_listeners()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct net_event_listener* listener;
|
||||||
|
|
||||||
|
|
||||||
|
hub_log(log_dump, "listeners: number=%d", num_connections);
|
||||||
|
|
||||||
|
for (i = 0; i < num_connections; i++)
|
||||||
|
{
|
||||||
|
listener = &listeners[i];
|
||||||
|
|
||||||
|
if (listener)
|
||||||
|
{
|
||||||
|
if (listener->fd != -1)
|
||||||
|
{
|
||||||
|
hub_log(log_dump, "epoll_dump_listeners: pos=%d/%d fd=%d, ptr=%p", i, num_connections, listeners->fd, listeners);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hub_log(log_dump, "epoll_dump_listeners: pos=%d/%d (unused)", i, num_connections);
|
||||||
|
}
|
||||||
|
|
||||||
|
listener = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getc(stdin);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static void set_poll_events(struct epoll_event* handle, short trigger)
|
||||||
|
{
|
||||||
|
memset(handle, 0, sizeof(struct epoll_event));
|
||||||
|
|
||||||
|
if (trigger & evt_accept || trigger & evt_read || trigger & evt_close)
|
||||||
|
handle->events |= EPOLLIN;
|
||||||
|
|
||||||
|
if (trigger & evt_write)
|
||||||
|
handle->events |= EPOLLOUT;
|
||||||
|
|
||||||
|
if (trigger & evt_urgent)
|
||||||
|
handle->events |= EPOLLPRI;
|
||||||
|
|
||||||
|
#ifdef EPOLLRDHUP
|
||||||
|
if (triggers & evt_close)
|
||||||
|
handle->events |= EPOLLRDHUP;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static short get_poll_events(struct epoll_event* handle)
|
||||||
|
{
|
||||||
|
short trig = handle->events;
|
||||||
|
short evt = 0;
|
||||||
|
|
||||||
|
if (trig & EPOLLIN)
|
||||||
|
evt |= evt_read;
|
||||||
|
|
||||||
|
if (trig & EPOLLPRI)
|
||||||
|
evt |= evt_urgent;
|
||||||
|
|
||||||
|
if (trig & EPOLLOUT)
|
||||||
|
evt |= evt_write;
|
||||||
|
|
||||||
|
if (trig & EPOLLHUP)
|
||||||
|
evt |= evt_close;
|
||||||
|
|
||||||
|
if (trig & EPOLLERR)
|
||||||
|
evt |= evt_error;
|
||||||
|
|
||||||
|
#ifdef EPOLLRDHUP
|
||||||
|
if (trig & EPOLLRDHUP)
|
||||||
|
evt |= evt_close;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return evt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int net_initialize(int capacity)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
max_connections = capacity;
|
||||||
|
num_connections = 0;
|
||||||
|
epfd = epoll_create(max_connections);
|
||||||
|
if (epfd == -1)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "net_initialize(): epoll_create failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
events = hub_malloc_zero(sizeof(struct epoll_event) * max_connections);
|
||||||
|
if (!events)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "net_initialize(): hub_malloc failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor_allocate((size_t) capacity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG_EPOLL
|
||||||
|
dump_listeners();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
net_stats_initialize();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int net_shutdown()
|
||||||
|
{
|
||||||
|
hub_log(log_trace, "Shutting down network monitor");
|
||||||
|
if (epfd != -1)
|
||||||
|
{
|
||||||
|
close(epfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
hub_free(events);
|
||||||
|
hub_free(listeners);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_EPOLL
|
||||||
|
uint64_t get_time_difference_in_msec(struct timeval before, struct timeval after)
|
||||||
|
{
|
||||||
|
uint64_t seconds = (after.tv_sec - before.tv_sec);
|
||||||
|
uint64_t out = seconds*1000;
|
||||||
|
if (seconds > 0)
|
||||||
|
out += ((after.tv_usec / 1000) + (1000 - (before.tv_usec / 1000)));
|
||||||
|
else
|
||||||
|
out += ((after.tv_usec - before.tv_usec) / 1000);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int net_wait(int timeout_ms)
|
||||||
|
{
|
||||||
|
int fired, n, max, ret;
|
||||||
|
struct net_event_listener* listener;
|
||||||
|
|
||||||
|
#ifdef DEBUG_EPOLL
|
||||||
|
struct timeval tm_before;
|
||||||
|
struct timeval tm_after;
|
||||||
|
gettimeofday(&tm_before, NULL);
|
||||||
|
dump_listeners();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fired = epoll_wait(epfd, events, num_connections, timeout_ms);
|
||||||
|
if (fired == -1) {
|
||||||
|
if (errno != EINTR)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "net_wait(): epoll_wait failed");
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (n = 0; n < fired; n++)
|
||||||
|
{
|
||||||
|
listener = (struct net_event_listener*) events[n].data.ptr;
|
||||||
|
listener->revents = get_poll_events(&events[n]);
|
||||||
|
hub_log(log_dump, "net_wait(): epoll event detected (fd=%d, evt=%d, ptr=%p)", listener->fd, listener->revents, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
max = num_connections;
|
||||||
|
|
||||||
|
for (n = 0; n < max; n++)
|
||||||
|
{
|
||||||
|
listener = &listeners[n];
|
||||||
|
if (listener && listener->fd != -1 && listener->revents)
|
||||||
|
{
|
||||||
|
hub_log(log_dump, "net_wait(): epoll trigger call (fd=%d, evt=%d, ptr=%p)", listener->fd, listener->revents, listener);
|
||||||
|
ret = listener->handler(listener);
|
||||||
|
listener->revents = 0;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_EPOLL
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (listener)
|
||||||
|
hub_log(log_dump, "net_wait(): epoll trigger ignore (fd=%d, evt=%d, ptr=%p)", listener->fd, listener->revents, listener);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_EPOLL
|
||||||
|
gettimeofday(&tm_after, NULL);
|
||||||
|
size_t diff = (size_t) get_time_difference_in_msec(tm_before, tm_after);
|
||||||
|
dump_listeners();
|
||||||
|
hub_log(log_debug, "net_wait(): time=%dms, triggered=%d", diff, fired);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int net_add(int fd, short events, void* data, net_event_handler_t handler)
|
||||||
|
{
|
||||||
|
struct epoll_event ev;
|
||||||
|
struct net_event_listener* listener = monitor_get_free_listener();
|
||||||
|
|
||||||
|
hub_log(log_trace, "net_add(): adding socket (fd=%d, pos=%d)", fd, pos);
|
||||||
|
|
||||||
|
if (!listener)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "net_add(): unable to poll more sockets");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
net_event_listener_set(listener, fd, events, data, handler);
|
||||||
|
|
||||||
|
set_poll_events(&ev, events);
|
||||||
|
ev.data.ptr = listener;
|
||||||
|
|
||||||
|
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "net_add(): epoll_ctl error while adding socket (fd=%d)", fd);
|
||||||
|
net_event_listener_clear(listener);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
num_connections++;
|
||||||
|
|
||||||
|
#ifdef DEBUG_EPOLL
|
||||||
|
dump_listeners();
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int net_modify(int fd, short events)
|
||||||
|
{
|
||||||
|
struct epoll_event ev;
|
||||||
|
struct net_event_listener* listener = monitor_get_listener(fd);
|
||||||
|
hub_log(log_trace, "net_modify(): modifying socket events (fd=%d)", fd);
|
||||||
|
|
||||||
|
if (!listener)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "net_modify(): unable to find socket.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
listener->events = events;
|
||||||
|
set_poll_events(&ev, events);
|
||||||
|
ev.data.ptr = listener;
|
||||||
|
|
||||||
|
if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) < 0)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "net_add(): epoll_ctl error while modifying socket (fd=%d)", fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_EPOLL
|
||||||
|
dump_listeners();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int net_remove(int fd)
|
||||||
|
{
|
||||||
|
struct epoll_event ev;
|
||||||
|
struct net_event_listener* listener = monitor_get_listener(fd);
|
||||||
|
|
||||||
|
hub_log(log_trace, "net_remove(): removing socket (fd=%d, pos=%d)", fd, pos);
|
||||||
|
|
||||||
|
if (!listener)
|
||||||
|
{
|
||||||
|
/* The socket is not being monitored */
|
||||||
|
hub_log(log_error, "net_remove(): unable to remove socket (fd=%d)", fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
net_event_listener_clear(listener);
|
||||||
|
|
||||||
|
if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev) < 0)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "net_remove(): epoll_ctl error while removing socket (fd=%d)", fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
num_connections--;
|
||||||
|
|
||||||
|
#ifdef DEBUG_EPOLL
|
||||||
|
dump_listeners();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HAVE_EPOLL */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
290
src/network-kqueue.c
Normal file
290
src/network-kqueue.c
Normal file
@@ -0,0 +1,290 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_KQUEUE
|
||||||
|
|
||||||
|
static struct kevent* events = 0;
|
||||||
|
static struct kevent* change = 0;
|
||||||
|
static int kfd = -1;
|
||||||
|
|
||||||
|
|
||||||
|
static void set_poll_events(struct kevent* handle, short trigger)
|
||||||
|
{
|
||||||
|
if (!handle) {
|
||||||
|
hub_log(log_error, "OOOPS!!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(handle, 0, sizeof(struct kevent));
|
||||||
|
|
||||||
|
if (trigger & evt_accept || trigger & evt_read || trigger & evt_close)
|
||||||
|
handle->filter |= EVFILT_READ;
|
||||||
|
|
||||||
|
if (trigger & evt_write /* || trigger & evt_accept*/)
|
||||||
|
handle->filter |= EVFILT_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static short get_poll_events(struct kevent* handle)
|
||||||
|
{
|
||||||
|
short trig = handle->flags;
|
||||||
|
short evt = 0;
|
||||||
|
|
||||||
|
if (trig & EVFILT_READ)
|
||||||
|
evt |= evt_read;
|
||||||
|
|
||||||
|
if (trig & EVFILT_WRITE)
|
||||||
|
evt |= evt_write;
|
||||||
|
|
||||||
|
if (trig & EV_EOF)
|
||||||
|
{
|
||||||
|
evt |= evt_close;
|
||||||
|
|
||||||
|
if (handle->fflags)
|
||||||
|
evt |= evt_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle->filter == -1)
|
||||||
|
{
|
||||||
|
|
||||||
|
evt |= evt_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle->data)
|
||||||
|
{
|
||||||
|
evt |= evt_accept;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evt)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "Evt: fd=%d, filter=%d, flags=%d, fflags=%d, data=%d evt=%#x", handle->ident, handle->filter, handle->flags, handle->fflags, (int) handle->data, evt);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return evt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int net_initialize(int capacity)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
max_connections = capacity;
|
||||||
|
num_connections = 0;
|
||||||
|
kfd = kqueue();
|
||||||
|
if (kfd == -1)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "net_initialize(): kqueue failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
events = (void*) hub_malloc_zero(sizeof(struct kevent) * max_connections);
|
||||||
|
if (!events)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "net_initialize(): hub_malloc failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
change = (void*) hub_malloc_zero(sizeof(struct kevent) * max_connections);
|
||||||
|
if (!events)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "net_initialize(): hub_malloc failed");
|
||||||
|
hub_free(events);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
listeners = (void*) hub_malloc_zero(sizeof(struct net_event_listener) * max_connections);
|
||||||
|
if (!listeners)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "net_initialize(): hub_malloc failed");
|
||||||
|
hub_free(change);
|
||||||
|
hub_free(events);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < max_connections; i++)
|
||||||
|
{
|
||||||
|
listeners[i].fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
net_stats_initialize();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int net_shutdown()
|
||||||
|
{
|
||||||
|
if (kfd != -1) {
|
||||||
|
return close(kfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
hub_free(events);
|
||||||
|
hub_free(change);
|
||||||
|
hub_free(listeners);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int net_wait(int timeout_ms)
|
||||||
|
{
|
||||||
|
int fired, n, max, ret;
|
||||||
|
struct net_event_listener* listener;
|
||||||
|
struct timespec timeout = { (timeout_ms / 1000), (timeout_ms % 1000) * 1000 };
|
||||||
|
|
||||||
|
fired = kevent(kfd, events, num_connections, change, num_connections, &timeout);
|
||||||
|
if (fired == -1) {
|
||||||
|
if (errno != EINTR)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "net_wait(): kevent failed");
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (n = 0; n < fired; n++)
|
||||||
|
{
|
||||||
|
listener = (struct net_event_listener*) events[n].udata;
|
||||||
|
if (listener)
|
||||||
|
{
|
||||||
|
listener->revents = get_poll_events(&events[n]);
|
||||||
|
hub_log(log_dump, "net_wait(): kqueue event detected (fd=%d, evt=%d, ptr=%p)", listener->fd, listener->revents, listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
max = num_connections;
|
||||||
|
for (n = 0; n < max; n++)
|
||||||
|
{
|
||||||
|
listener = &listeners[n];
|
||||||
|
if (listener && listener->fd != -1 && listener->revents != 0)
|
||||||
|
{
|
||||||
|
hub_log(log_dump, "net_wait(): kqueue trigger call (fd=%d, evt=%d, ptr=%p)", listener->fd, listener->revents, listener);
|
||||||
|
ret = listener->handler(listener);
|
||||||
|
listener->revents = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int net_add(int fd, short events_, void* data, net_event_handler_t handler)
|
||||||
|
{
|
||||||
|
struct kevent* event;
|
||||||
|
struct net_event_listener* listener = monitor_get_listener(fd);
|
||||||
|
|
||||||
|
hub_log(log_trace, "net_add(): adding socket (fd=%d)", fd);
|
||||||
|
|
||||||
|
if (listener)
|
||||||
|
{
|
||||||
|
/* Already added! */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
listener = monitor_get_free_listener();
|
||||||
|
if (!listener)
|
||||||
|
{
|
||||||
|
hub_log(log_error, "net_add(): unable to poll more sockets");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
net_event_listener_set(listener, fd, events_, data, handler);
|
||||||
|
|
||||||
|
event = &events[pos];
|
||||||
|
set_poll_events(event, events_);
|
||||||
|
event->ident = fd;
|
||||||
|
|
||||||
|
event->flags |= EV_ADD;
|
||||||
|
event->flags |= EV_ONESHOT;
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
event->flags |= EV_ENABLE;
|
||||||
|
#endif
|
||||||
|
event->udata = listener;
|
||||||
|
|
||||||
|
num_connections++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int net_modify(int fd, short events_)
|
||||||
|
{
|
||||||
|
struct kevent* event;
|
||||||
|
struct net_event_listener* listener = monitor_get_listener(fd);
|
||||||
|
|
||||||
|
hub_log(log_trace, "net_modify(): modifying socket (fd=%d)", fd);
|
||||||
|
|
||||||
|
if (!listener)
|
||||||
|
{
|
||||||
|
/* The socket is not being monitored */
|
||||||
|
hub_log(log_error, "net_modify(): unable to find socket (fd=%d)", fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
event = &events[pos];
|
||||||
|
// set_poll_events(event, events_);
|
||||||
|
|
||||||
|
event->ident = fd;
|
||||||
|
event->flags |= EV_ADD;
|
||||||
|
event->flags |= EV_ONESHOT;
|
||||||
|
#ifdef __APPLE__
|
||||||
|
event->flags |= EV_ENABLE;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int net_remove(int fd)
|
||||||
|
{
|
||||||
|
struct kevent* event;
|
||||||
|
struct net_event_listener* listener = monitor_get_listener(fd);
|
||||||
|
|
||||||
|
hub_log(log_trace, "net_remove(): removing socket (fd=%d)", fd);
|
||||||
|
|
||||||
|
if (!listener)
|
||||||
|
{
|
||||||
|
/* The socket is not being monitored */
|
||||||
|
hub_log(log_error, "net_remove(): unable to remove socket (fd=%d)", fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
net_event_listener_clear(listener);
|
||||||
|
|
||||||
|
event = &events[pos];
|
||||||
|
event->ident = fd;
|
||||||
|
event->filter = 0;
|
||||||
|
event->flags = EV_DELETE;
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
event->flasg |= EV_DISABLE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
event->fflags = 0;
|
||||||
|
event->data = 0;
|
||||||
|
event->udata = 0;
|
||||||
|
|
||||||
|
num_connections--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HAVE_KQUEUE */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
static int is_ipv6_supported = -1; /* -1 = CHECK, 0 = NO, 1 = YES */
|
static int is_ipv6_supported = -1; /* -1 = CHECK, 0 = NO, 1 = YES */
|
||||||
static int net_initialized = 0;
|
static int net_initialized = 0;
|
||||||
|
|
||||||
static struct net_statistics stats;
|
static struct net_statistics stats;
|
||||||
static struct net_statistics stats_total;
|
static struct net_statistics stats_total;
|
||||||
|
|
||||||
@@ -36,31 +35,21 @@ int net_initialize()
|
|||||||
{
|
{
|
||||||
if (!net_initialized)
|
if (!net_initialized)
|
||||||
{
|
{
|
||||||
LOG_TRACE("Initializing network monitor.");
|
|
||||||
|
|
||||||
#ifdef WINSOCK
|
#ifdef WINSOCK
|
||||||
struct WSAData wsa;
|
struct WSAData wsa;
|
||||||
if (WSAStartup(MAKEWORD(2, 2), &wsa) != NO_ERROR)
|
if (WSAStartup(MAKEWORD(2, 2), &wsa) != NO_ERROR)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Unable to initialize winsock.");
|
hub_log(log_error, "Unable to initialize winsock.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif /* WINSOCK */
|
#endif /* WINSOCK */
|
||||||
|
|
||||||
if (!net_backend_init())
|
hub_log(log_trace, "Initializing network monitor.");
|
||||||
{
|
|
||||||
#ifdef WINSOCK
|
|
||||||
WSACleanup();
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
net_stats_initialize();
|
net_stats_initialize();
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
LOG_TRACE("Initializing OpenSSL...");
|
/* FIXME: Initialize OpenSSL here. */
|
||||||
SSL_library_init();
|
|
||||||
SSL_load_error_strings();
|
|
||||||
OpenSSL_add_all_algorithms();
|
|
||||||
#endif /* SSL_SUPPORT */
|
#endif /* SSL_SUPPORT */
|
||||||
|
|
||||||
net_initialized = 1;
|
net_initialized = 1;
|
||||||
@@ -69,35 +58,12 @@ int net_initialize()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t net_get_max_sockets()
|
|
||||||
{
|
|
||||||
#ifdef HAVE_GETRLIMIT
|
|
||||||
struct rlimit limits;
|
|
||||||
if (getrlimit(RLIMIT_NOFILE, &limits) == 0)
|
|
||||||
{
|
|
||||||
return MIN(limits.rlim_max, 65536);
|
|
||||||
}
|
|
||||||
LOG_ERROR("getrlimit() failed");
|
|
||||||
return 1024;
|
|
||||||
#else
|
|
||||||
#ifdef WIN32
|
|
||||||
LOG_WARN("Windows system, limited to 4096 connections.");
|
|
||||||
return 4096;
|
|
||||||
#else
|
|
||||||
LOG_WARN("System does not have getrlimit(): constrained to 1024 sockets");
|
|
||||||
return 1024;
|
|
||||||
#endif
|
|
||||||
#endif /* HAVE_GETRLIMIT */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
int net_shutdown()
|
||||||
int net_destroy()
|
|
||||||
{
|
{
|
||||||
if (net_initialized)
|
if (net_initialized)
|
||||||
{
|
{
|
||||||
LOG_TRACE("Shutting down network monitor");
|
hub_log(log_trace, "Shutting down network monitor");
|
||||||
|
|
||||||
net_backend_shutdown();
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
/* FIXME: Shutdown OpenSSL here. */
|
/* FIXME: Shutdown OpenSSL here. */
|
||||||
@@ -112,18 +78,6 @@ int net_destroy()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_LIBEVENT
|
|
||||||
struct event_base* net_get_evbase()
|
|
||||||
{
|
|
||||||
return net_evbase;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void net_error_out(int fd, const char* func)
|
|
||||||
{
|
|
||||||
int err = net_error();
|
|
||||||
LOG_ERROR("%s, fd=%d: %s (%d)", func, fd, net_error_string(err), err);
|
|
||||||
}
|
|
||||||
|
|
||||||
int net_error()
|
int net_error()
|
||||||
{
|
{
|
||||||
@@ -149,81 +103,60 @@ const char* net_error_string(int code)
|
|||||||
|
|
||||||
static int net_setsockopt(int fd, int level, int opt, const void* optval, socklen_t optlen)
|
static int net_setsockopt(int fd, int level, int opt, const void* optval, socklen_t optlen)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
|
||||||
#ifdef WINSOCK
|
#ifdef WINSOCK
|
||||||
ret = setsockopt(fd, level, opt, (const char*) optval, optlen);
|
return setsockopt(fd, level, opt, (const char*) optval, optlen);
|
||||||
#else
|
#else
|
||||||
ret = setsockopt(fd, level, opt, optval, optlen);
|
return setsockopt(fd, level, opt, optval, optlen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ret == -1)
|
|
||||||
{
|
|
||||||
net_error_out(fd, "net_setsockopt");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int net_getsockopt(int fd, int level, int opt, void* optval, socklen_t* optlen)
|
|
||||||
{
|
|
||||||
int ret = -1;
|
|
||||||
#ifdef WINSOCK
|
|
||||||
ret = getsockopt(fd, level, opt, (char*) optval, optlen);
|
|
||||||
#else
|
|
||||||
ret = getsockopt(fd, level, opt, optval, optlen);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ret == -1)
|
|
||||||
{
|
|
||||||
net_error_out(fd, "net_getsockopt");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int net_set_nonblocking(int fd, int toggle)
|
int net_set_nonblocking(int fd, int toggle)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret;
|
||||||
|
|
||||||
|
#ifdef NETAPI_DUMP
|
||||||
|
hub_log(log_dump, "net_set_nonblocking(): fd=%d", fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WINSOCK
|
#ifdef WINSOCK
|
||||||
u_long on = toggle ? 1 : 0;
|
u_long on = toggle ? 1 : 0;
|
||||||
ret = ioctlsocket(fd, FIONBIO, &on);
|
ret = ioctlsocket(fd, FIONBIO, &on);
|
||||||
#else
|
|
||||||
#ifdef __sun__
|
|
||||||
int flags = fcntl(fd, F_GETFL, 0);
|
|
||||||
if (flags != -1)
|
|
||||||
{
|
|
||||||
if (toggle) flags |= O_NONBLOCK;
|
|
||||||
else flags &= ~O_NONBLOCK;
|
|
||||||
ret = fcntl(fd, F_SETFL, flags);
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
ret = ioctl(fd, FIONBIO, &toggle);
|
ret = ioctl(fd, FIONBIO, &toggle);
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
net_error_out(fd, "net_set_nonblocking");
|
hub_log(log_error, "net_set_nonblocking(): ioctl failed (fd=%d): %s", fd, net_error_string(net_error()));
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* NOTE: Possibly only supported on BSD and OSX? */
|
/* NOTE: Possibly only supported on BSD and OSX? */
|
||||||
int net_set_nosigpipe(int fd, int toggle)
|
int net_set_nosigpipe(int fd, int toggle)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
|
||||||
#ifdef SO_NOSIGPIPE
|
#ifdef SO_NOSIGPIPE
|
||||||
|
int ret;
|
||||||
|
#ifdef NETAPI_DUMP
|
||||||
|
hub_log(log_dump, "net_set_nosigpipe(): fd=%d", fd);
|
||||||
|
#endif
|
||||||
ret = net_setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &toggle, sizeof(toggle));
|
ret = net_setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &toggle, sizeof(toggle));
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
net_error_out(fd, "net_set_nosigpipe");
|
hub_log(log_error, "net_set_linger(): setsockopt failed (fd=%d): %s", fd, net_error_string(net_error()));
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int net_set_close_on_exec(int fd, int toggle)
|
int net_set_close_on_exec(int fd, int toggle)
|
||||||
{
|
{
|
||||||
|
#ifdef NETAPI_DUMP
|
||||||
|
hub_log(log_dump, "net_set_close_on_exec(): fd=%d", fd);
|
||||||
|
#endif
|
||||||
#ifdef WINSOCK
|
#ifdef WINSOCK
|
||||||
return -1; /* FIXME: How is this done on Windows? */
|
return -1; /* FIXME: How is this done on Windows? */
|
||||||
#else
|
#else
|
||||||
@@ -231,63 +164,54 @@ int net_set_close_on_exec(int fd, int toggle)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int net_set_linger(int fd, int toggle)
|
int net_set_linger(int fd, int toggle)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
#ifdef NETAPI_DUMP
|
||||||
|
hub_log(log_dump, "net_set_linger(): fd=%d", fd);
|
||||||
|
#endif
|
||||||
ret = net_setsockopt(fd, SOL_SOCKET, SO_LINGER, &toggle, sizeof(toggle));
|
ret = net_setsockopt(fd, SOL_SOCKET, SO_LINGER, &toggle, sizeof(toggle));
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
net_error_out(fd, "net_set_linger");
|
hub_log(log_error, "net_set_linger(): setsockopt failed (fd=%d): %s", fd, net_error_string(net_error()));
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int net_set_keepalive(int fd, int toggle)
|
int net_set_keepalive(int fd, int toggle)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
#ifdef NETAPI_DUMP
|
||||||
|
hub_log(log_dump, "net_set_keepalive(): fd=%d", fd);
|
||||||
|
#endif
|
||||||
ret = net_setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &toggle, sizeof(toggle));
|
ret = net_setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &toggle, sizeof(toggle));
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
net_error_out(fd, "net_set_keepalive");
|
hub_log(log_error, "net_set_keepalive(): setsockopt failed (fd=%d): %s", fd, net_error_string(net_error()));
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int net_set_reuseaddress(int fd, int toggle)
|
int net_set_reuseaddress(int fd, int toggle)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
#ifdef NETAPI_DUMP
|
||||||
|
hub_log(log_dump, "net_set_reuseaddress(): fd=%d", fd);
|
||||||
|
#endif
|
||||||
ret = net_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &toggle, sizeof(toggle));
|
ret = net_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &toggle, sizeof(toggle));
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
net_error_out(fd, "net_set_reuseaddress");
|
hub_log(log_error, "net_set_reuseaddress(): setsockopt failed (fd=%d): %s", fd, net_error_string(net_error()));
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int net_set_sendbuf_size(int fd, size_t size)
|
|
||||||
{
|
|
||||||
return net_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
|
|
||||||
}
|
|
||||||
|
|
||||||
int net_get_sendbuf_size(int fd, size_t* size)
|
|
||||||
{
|
|
||||||
socklen_t sz = sizeof(*size);
|
|
||||||
return net_getsockopt(fd, SOL_SOCKET, SO_SNDBUF, size, &sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
int net_set_recvbuf_size(int fd, size_t size)
|
|
||||||
{
|
|
||||||
return net_setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
|
|
||||||
}
|
|
||||||
|
|
||||||
int net_get_recvbuf_size(int fd, size_t* size)
|
|
||||||
{
|
|
||||||
socklen_t sz = sizeof(*size);
|
|
||||||
return net_getsockopt(fd, SOL_SOCKET, SO_RCVBUF, size, &sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int net_close(int fd)
|
int net_close(int fd)
|
||||||
{
|
{
|
||||||
@@ -303,7 +227,7 @@ int net_close(int fd)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ret != -1)
|
if (fd != -1)
|
||||||
{
|
{
|
||||||
net_stats_add_error();
|
net_stats_add_error();
|
||||||
}
|
}
|
||||||
@@ -311,32 +235,6 @@ int net_close(int fd)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int net_shutdown_r(int fd)
|
|
||||||
{
|
|
||||||
#ifdef WINSOCK
|
|
||||||
return shutdown(fd, SD_RECEIVE);
|
|
||||||
#else
|
|
||||||
return shutdown(fd, SHUT_RD);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int net_shutdown_w(int fd)
|
|
||||||
{
|
|
||||||
#ifdef WINSOCK
|
|
||||||
return shutdown(fd, SD_SEND);
|
|
||||||
#else
|
|
||||||
return shutdown(fd, SHUT_WR);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int net_shutdown_rw(int fd)
|
|
||||||
{
|
|
||||||
#ifdef WINSOCK
|
|
||||||
return shutdown(fd, SD_BOTH);
|
|
||||||
#else
|
|
||||||
return shutdown(fd, SHUT_RDWR);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int net_accept(int fd, struct ip_addr_encap* ipaddr)
|
int net_accept(int fd, struct ip_addr_encap* ipaddr)
|
||||||
{
|
{
|
||||||
@@ -357,9 +255,6 @@ int net_accept(int fd, struct ip_addr_encap* ipaddr)
|
|||||||
{
|
{
|
||||||
switch (net_error())
|
switch (net_error())
|
||||||
{
|
{
|
||||||
#if defined(__HAIKU__)
|
|
||||||
case ETIMEDOUT:
|
|
||||||
#endif
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
case ENETDOWN:
|
case ENETDOWN:
|
||||||
case EPROTO:
|
case EPROTO:
|
||||||
@@ -373,7 +268,7 @@ int net_accept(int fd, struct ip_addr_encap* ipaddr)
|
|||||||
case EWOULDBLOCK:
|
case EWOULDBLOCK:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
net_error_out(fd, "net_accept");
|
hub_log(log_error, "net_accept(): accept failed (fd=%d, errno=%d, msg=%s)", fd, net_error(), net_error_string(net_error()));
|
||||||
net_stats_add_error();
|
net_stats_add_error();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -385,22 +280,11 @@ int net_accept(int fd, struct ip_addr_encap* ipaddr)
|
|||||||
if (ipaddr)
|
if (ipaddr)
|
||||||
{
|
{
|
||||||
memset(ipaddr, 0, sizeof(struct ip_addr_encap));
|
memset(ipaddr, 0, sizeof(struct ip_addr_encap));
|
||||||
ipaddr->af = addr.ss_family;;
|
ipaddr->af = addr4->sin_family;
|
||||||
if (ipaddr->af == AF_INET6)
|
if (ipaddr->af == AF_INET6)
|
||||||
{
|
|
||||||
char address[INET6_ADDRSTRLEN+1] = { 0, };
|
|
||||||
net_address_to_string(AF_INET6, (void*) &addr6->sin6_addr, address, INET6_ADDRSTRLEN+1);
|
|
||||||
if (strchr(address, '.'))
|
|
||||||
{
|
|
||||||
/* Hack to convert IPv6 mapped IPv4 addresses to true IPv4 addresses */
|
|
||||||
ipaddr->af = AF_INET;
|
|
||||||
net_string_to_address(AF_INET, address, (void*) &ipaddr->internal_ip_data.in);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
memcpy(&ipaddr->internal_ip_data.in6, &addr6->sin6_addr, sizeof(struct in6_addr));
|
memcpy(&ipaddr->internal_ip_data.in6, &addr6->sin6_addr, sizeof(struct in6_addr));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy(&ipaddr->internal_ip_data.in, &addr4->sin_addr, sizeof(struct in_addr));
|
memcpy(&ipaddr->internal_ip_data.in, &addr4->sin_addr, sizeof(struct in_addr));
|
||||||
@@ -419,7 +303,7 @@ int net_connect(int fd, const struct sockaddr *serv_addr, socklen_t addrlen)
|
|||||||
{
|
{
|
||||||
if (net_error() != EINPROGRESS)
|
if (net_error() != EINPROGRESS)
|
||||||
{
|
{
|
||||||
net_error_out(fd, "net_connect");
|
hub_log(log_error, "net_connect(): connect failed (fd=%d, errno=%d, msg=%s)", fd, net_error(), net_error_string(net_error()));
|
||||||
net_stats_add_error();
|
net_stats_add_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -441,12 +325,13 @@ int net_is_ipv6_supported()
|
|||||||
if (net_error() == EAFNOSUPPORT)
|
if (net_error() == EAFNOSUPPORT)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
LOG_TRACE("net_is_ipv6_supported(): IPv6 is not supported on this system.");
|
hub_log(log_trace, "net_is_ipv6_supported(): IPv6 is not supported on this system.");
|
||||||
is_ipv6_supported = 0;
|
is_ipv6_supported = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
net_error_out(ret, "net_is_ipv6_supported");
|
hub_log(log_error, "net_is_ipv6_supported(): Unknown error (errno=%d, msg=%s)", net_error(), net_error_string(net_error()));
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -454,7 +339,7 @@ int net_is_ipv6_supported()
|
|||||||
int off = 0;
|
int off = 0;
|
||||||
if (net_setsockopt(ret, IPPROTO_IPV6, SOCK_DUAL_STACK_OPT, (char*) &off, sizeof(off)) < 0)
|
if (net_setsockopt(ret, IPPROTO_IPV6, SOCK_DUAL_STACK_OPT, (char*) &off, sizeof(off)) < 0)
|
||||||
{
|
{
|
||||||
LOG_ERROR("net_socket_create(): Dual stack IPv6/IPv4 is not supported.");
|
hub_log(log_error, "net_socket_create(): Dual stack IPv6/IPv4 is not supported.");
|
||||||
is_ipv6_supported = 0;
|
is_ipv6_supported = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -476,8 +361,7 @@ int net_socket_create(int af, int type, int protocol)
|
|||||||
int sd = socket(af, type, protocol);
|
int sd = socket(af, type, protocol);
|
||||||
if (sd == -1)
|
if (sd == -1)
|
||||||
{
|
{
|
||||||
net_error_out(sd, "net_socket_create");
|
hub_log(log_error, "net_socket_create(): socket failed (errno=%d, msg=%s)", net_error(), net_error_string(net_error()));
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SOCK_DUAL_STACK_OPT
|
#ifdef SOCK_DUAL_STACK_OPT
|
||||||
@@ -487,7 +371,7 @@ int net_socket_create(int af, int type, int protocol)
|
|||||||
int off = 0;
|
int off = 0;
|
||||||
if (net_setsockopt(sd, IPPROTO_IPV6, SOCK_DUAL_STACK_OPT, (char*) &off, sizeof(off)) < 0)
|
if (net_setsockopt(sd, IPPROTO_IPV6, SOCK_DUAL_STACK_OPT, (char*) &off, sizeof(off)) < 0)
|
||||||
{
|
{
|
||||||
LOG_ERROR("net_socket_create(): Cannot set socket to dual stack mode IPv6/IPv4 (%d - %s).", net_error(), net_error_string(net_error()));
|
hub_log(log_error, "net_socket_create(): Cannot set socket to dual stack mode IPv6/IPv4 (%d - %s).", net_error(), net_error_string(net_error()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -535,15 +419,7 @@ const char* net_address_to_string(int af, const void* src, char* dst, socklen_t
|
|||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
#else
|
#else
|
||||||
if (inet_ntop(af, src, dst, cnt))
|
return inet_ntop(af, src, dst, cnt);
|
||||||
{
|
|
||||||
if (af == AF_INET6 && strncmp(dst, "::ffff:", 7) == 0) /* IPv6 mapped IPv4 address. */
|
|
||||||
{
|
|
||||||
memmove(dst, dst + 7, cnt - 7);
|
|
||||||
}
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,6 +466,9 @@ int net_string_to_address(int af, const char* src, void* dst)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char* net_get_peer_address(int fd)
|
const char* net_get_peer_address(int fd)
|
||||||
{
|
{
|
||||||
static char address[INET6_ADDRSTRLEN+1];
|
static char address[INET6_ADDRSTRLEN+1];
|
||||||
@@ -597,10 +476,9 @@ const char* net_get_peer_address(int fd)
|
|||||||
struct sockaddr_in6* name6;
|
struct sockaddr_in6* name6;
|
||||||
struct sockaddr_in* name4;
|
struct sockaddr_in* name4;
|
||||||
struct sockaddr* name;
|
struct sockaddr* name;
|
||||||
socklen_t namelen;
|
|
||||||
|
|
||||||
memset(address, 0, INET6_ADDRSTRLEN);
|
memset(address, 0, INET6_ADDRSTRLEN);
|
||||||
namelen = sizeof(struct sockaddr_storage);
|
socklen_t namelen = sizeof(struct sockaddr_storage);
|
||||||
memset(&storage, 0, namelen);
|
memset(&storage, 0, namelen);
|
||||||
|
|
||||||
name6 = (struct sockaddr_in6*) &storage;
|
name6 = (struct sockaddr_in6*) &storage;
|
||||||
@@ -609,67 +487,33 @@ const char* net_get_peer_address(int fd)
|
|||||||
|
|
||||||
if (getpeername(fd, (struct sockaddr*) name, &namelen) != -1)
|
if (getpeername(fd, (struct sockaddr*) name, &namelen) != -1)
|
||||||
{
|
{
|
||||||
int af = storage.ss_family;
|
int af = name4->sin_family;
|
||||||
if (af == AF_INET6)
|
if (af == AF_INET6)
|
||||||
{
|
{
|
||||||
net_address_to_string(af, (void*) &name6->sin6_addr, address, INET6_ADDRSTRLEN);
|
net_address_to_string(af, (void*) &name6->sin6_addr, address, INET6_ADDRSTRLEN);
|
||||||
}
|
if (strncmp(address, "::ffff:", 7) == 0) /* IPv6 mapped IPv4 address. */
|
||||||
else
|
|
||||||
{
|
{
|
||||||
net_address_to_string(af, (void*) &name4->sin_addr, address, INET6_ADDRSTRLEN);
|
return &address[7];
|
||||||
}
|
}
|
||||||
|
hub_log(log_trace, "net_get_peer_address(): address=%s", address);
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
net_error_out(fd, "net_get_peer_address");
|
|
||||||
net_stats_add_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
return "0.0.0.0";
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* net_get_local_address(int fd)
|
|
||||||
{
|
|
||||||
static char address[INET6_ADDRSTRLEN+1];
|
|
||||||
struct sockaddr_storage storage;
|
|
||||||
struct sockaddr_in6* name6;
|
|
||||||
struct sockaddr_in* name4;
|
|
||||||
struct sockaddr* name;
|
|
||||||
socklen_t namelen;
|
|
||||||
|
|
||||||
memset(address, 0, INET6_ADDRSTRLEN);
|
|
||||||
namelen = sizeof(struct sockaddr_storage);
|
|
||||||
memset(&storage, 0, namelen);
|
|
||||||
|
|
||||||
name6 = (struct sockaddr_in6*) &storage;
|
|
||||||
name4 = (struct sockaddr_in*) &storage;
|
|
||||||
name = (struct sockaddr*) &storage;
|
|
||||||
|
|
||||||
if (getsockname(fd, (struct sockaddr*) name, &namelen) != -1)
|
|
||||||
{
|
|
||||||
int af = storage.ss_family;
|
|
||||||
if (af == AF_INET6)
|
|
||||||
{
|
|
||||||
net_address_to_string(af, (void*) &name6->sin6_addr, address, INET6_ADDRSTRLEN);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
net_address_to_string(af, (void*) &name4->sin_addr, address, INET6_ADDRSTRLEN);
|
net_address_to_string(af, (void*) &name4->sin_addr, address, INET6_ADDRSTRLEN);
|
||||||
}
|
hub_log(log_trace, "net_get_peer_address(): address=%s", address);
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
net_error_out(fd, "net_get_local_address");
|
hub_log(log_error, "net_get_peer_address(): getsockname failed (fd=%d, errno=%d, msg=%s)", fd, net_error(), net_error_string(net_error()));
|
||||||
net_stats_add_error();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "0.0.0.0";
|
return "0.0.0.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ssize_t net_recv(int fd, void* buf, size_t len, int flags)
|
ssize_t net_recv(int fd, void* buf, size_t len, int flags)
|
||||||
{
|
{
|
||||||
ssize_t ret = recv(fd, buf, len, flags);
|
ssize_t ret = recv(fd, buf, len, flags);
|
||||||
@@ -681,7 +525,7 @@ ssize_t net_recv(int fd, void* buf, size_t len, int flags)
|
|||||||
{
|
{
|
||||||
if (net_error() != EWOULDBLOCK)
|
if (net_error() != EWOULDBLOCK)
|
||||||
{
|
{
|
||||||
/* net_error_out(fd, "net_recv"); */
|
hub_log(log_debug, "net_recv(): failed (fd=%d, errno=%d, msg=%s)", fd, net_error(), net_error_string(net_error()));
|
||||||
net_stats_add_error();
|
net_stats_add_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -689,7 +533,7 @@ ssize_t net_recv(int fd, void* buf, size_t len, int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t net_send(int fd, const void* buf, size_t len, int flags)
|
ssize_t net_send(int fd, void* buf, size_t len, int flags)
|
||||||
{
|
{
|
||||||
ssize_t ret = send(fd, buf, len, flags);
|
ssize_t ret = send(fd, buf, len, flags);
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
@@ -700,7 +544,7 @@ ssize_t net_send(int fd, const void* buf, size_t len, int flags)
|
|||||||
{
|
{
|
||||||
if (net_error() != EWOULDBLOCK)
|
if (net_error() != EWOULDBLOCK)
|
||||||
{
|
{
|
||||||
/* net_error_out(fd, "net_send"); */
|
hub_log(log_debug, "net_send(): failed (fd=%d, errno=%d, msg=%s)", fd, net_error(), net_error_string(net_error()));
|
||||||
net_stats_add_error();
|
net_stats_add_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -713,7 +557,7 @@ int net_bind(int fd, const struct sockaddr *my_addr, socklen_t addrlen)
|
|||||||
int ret = bind(fd, my_addr, addrlen);
|
int ret = bind(fd, my_addr, addrlen);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
net_error_out(fd, "net_bind");
|
hub_log(log_error, "net_bind(): failed (fd=%d, errno=%d, msg=%s)", fd, net_error(), net_error_string(net_error()));
|
||||||
net_stats_add_error();
|
net_stats_add_error();
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@@ -725,7 +569,7 @@ int net_listen(int fd, int backlog)
|
|||||||
int ret = listen(fd, backlog);
|
int ret = listen(fd, backlog);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
net_error_out(fd, "net_listen");
|
hub_log(log_error, "net_listen(): failed (fd=%d, errno=%d, msg=%s)", fd, net_error(), net_error_string(net_error()));
|
||||||
net_stats_add_error();
|
net_stats_add_error();
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@@ -741,12 +585,14 @@ void net_stats_initialize()
|
|||||||
stats.timestamp = time(NULL);
|
stats.timestamp = time(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void net_stats_get(struct net_statistics** intermediate, struct net_statistics** total)
|
void net_stats_get(struct net_statistics** intermediate, struct net_statistics** total)
|
||||||
{
|
{
|
||||||
*intermediate = &stats;
|
*intermediate = &stats;
|
||||||
*total = &stats_total;
|
*total = &stats_total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void net_stats_reset()
|
void net_stats_reset()
|
||||||
{
|
{
|
||||||
stats_total.tx += stats.tx;
|
stats_total.tx += stats.tx;
|
||||||
@@ -759,31 +605,37 @@ void net_stats_reset()
|
|||||||
stats.timestamp = time(NULL);
|
stats.timestamp = time(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int net_stats_timeout()
|
int net_stats_timeout()
|
||||||
{
|
{
|
||||||
return (difftime(time(NULL), stats.timestamp) > TIMEOUT_STATS) ? 1 : 0;
|
return (difftime(time(NULL), stats.timestamp) > TIMEOUT_STATS) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void net_stats_add_tx(size_t bytes)
|
void net_stats_add_tx(size_t bytes)
|
||||||
{
|
{
|
||||||
stats.tx += bytes;
|
stats.tx += bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void net_stats_add_rx(size_t bytes)
|
void net_stats_add_rx(size_t bytes)
|
||||||
{
|
{
|
||||||
stats.rx += bytes;
|
stats.rx += bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void net_stats_add_accept()
|
void net_stats_add_accept()
|
||||||
{
|
{
|
||||||
stats.accept++;
|
stats.accept++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void net_stats_add_error()
|
void net_stats_add_error()
|
||||||
{
|
{
|
||||||
stats.errors++;
|
stats.errors++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void net_stats_add_close()
|
void net_stats_add_close()
|
||||||
{
|
{
|
||||||
stats.closed++;
|
stats.closed++;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* uhub - A tiny ADC p2p connection hub
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -30,8 +30,6 @@ struct net_statistics
|
|||||||
size_t errors;
|
size_t errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct net_socket_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the socket monitor subsystem.
|
* Initialize the socket monitor subsystem.
|
||||||
* On some operating systems this will also involve loading the TCP/IP stack
|
* On some operating systems this will also involve loading the TCP/IP stack
|
||||||
@@ -49,9 +47,7 @@ extern int net_initialize();
|
|||||||
*
|
*
|
||||||
* @return -1 on error, 0 on success
|
* @return -1 on error, 0 on success
|
||||||
*/
|
*/
|
||||||
extern int net_destroy();
|
extern int net_shutdown();
|
||||||
|
|
||||||
extern struct event_base* net_get_evbase();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the number of sockets currrently being monitored.
|
* @return the number of sockets currrently being monitored.
|
||||||
@@ -80,20 +76,11 @@ extern const char* net_error_string(int code);
|
|||||||
*/
|
*/
|
||||||
extern int net_socket_create(int af, int type, int protocol);
|
extern int net_socket_create(int af, int type, int protocol);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the maximum number of file/socket descriptors.
|
|
||||||
*/
|
|
||||||
extern size_t net_get_max_sockets();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wrapper for the close() function call.
|
* A wrapper for the close() function call.
|
||||||
*/
|
*/
|
||||||
extern int net_close(int fd);
|
extern int net_close(int fd);
|
||||||
|
|
||||||
extern int net_shutdown_r(int fd);
|
|
||||||
extern int net_shutdown_w(int fd);
|
|
||||||
extern int net_shutdown_rw(int fd);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wrapper for the accept() function call.
|
* A wrapper for the accept() function call.
|
||||||
* @param fd socket descriptor
|
* @param fd socket descriptor
|
||||||
@@ -164,38 +151,6 @@ extern int net_set_linger(int fd, int toggle);
|
|||||||
*/
|
*/
|
||||||
extern int net_set_reuseaddress(int fd, int toggle);
|
extern int net_set_reuseaddress(int fd, int toggle);
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the send buffer size for the socket.
|
|
||||||
* @param fd socket descriptor
|
|
||||||
* @param size size to set
|
|
||||||
* @return -1 on error, 0 on success.
|
|
||||||
*/
|
|
||||||
extern int net_set_sendbuf_size(int fd, size_t size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the send buffer size for the socket.
|
|
||||||
* @param fd socket descriptor
|
|
||||||
* @param[out] size existing size, cannot be NULL.
|
|
||||||
* @return -1 on error, 0 on success.
|
|
||||||
*/
|
|
||||||
extern int net_get_sendbuf_size(int fd, size_t* size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the receive buffer size for the socket.
|
|
||||||
* @param fd socket descriptor
|
|
||||||
* @param size size to set
|
|
||||||
* @return -1 on error, 0 on success.
|
|
||||||
*/
|
|
||||||
extern int net_set_recvbuf_size(int fd, size_t size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the receive buffer size for the socket.
|
|
||||||
* @param fd socket descriptor
|
|
||||||
* @param[out] size existing size, cannot be NULL.
|
|
||||||
* @return -1 on error, 0 on success.
|
|
||||||
*/
|
|
||||||
extern int net_get_recvbuf_size(int fd, size_t* size);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wrapper for the recv() function call.
|
* A wrapper for the recv() function call.
|
||||||
*/
|
*/
|
||||||
@@ -204,7 +159,7 @@ extern ssize_t net_recv(int fd, void* buf, size_t len, int flags);
|
|||||||
/**
|
/**
|
||||||
* A wrapper for the send() function call.
|
* A wrapper for the send() function call.
|
||||||
*/
|
*/
|
||||||
extern ssize_t net_send(int fd, const void* buf, size_t len, int flags);
|
extern ssize_t net_send(int fd, void* buf, size_t len, int flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This tries to create a AF_INET6 socket.
|
* This tries to create a AF_INET6 socket.
|
||||||
@@ -224,8 +179,6 @@ extern int net_is_ipv6_supported();
|
|||||||
*/
|
*/
|
||||||
extern const char* net_get_peer_address(int fd);
|
extern const char* net_get_peer_address(int fd);
|
||||||
|
|
||||||
extern const char* net_get_local_address(int fd);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See man(3) inet_ntop.
|
* See man(3) inet_ntop.
|
||||||
*/
|
*/
|
||||||
@@ -257,6 +210,11 @@ extern void net_stats_get(struct net_statistics** intermediate, struct net_stati
|
|||||||
|
|
||||||
#if defined(WINSOCK) && !defined(__CYGWIN__)
|
#if defined(WINSOCK) && !defined(__CYGWIN__)
|
||||||
|
|
||||||
|
// #define EINTR WSAEINTR
|
||||||
|
// #define EACCES WSAEACCES
|
||||||
|
// #define EFAULT WSAEFAULT
|
||||||
|
// #define EINVAL WSAEINVAL
|
||||||
|
// #define EMFILE WSAEMFILE
|
||||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||||
#define EINPROGRESS WSAEINPROGRESS
|
#define EINPROGRESS WSAEINPROGRESS
|
||||||
#define EALREADY WSAEALREADY
|
#define EALREADY WSAEALREADY
|
||||||
@@ -285,8 +243,10 @@ extern void net_stats_get(struct net_statistics** intermediate, struct net_stati
|
|||||||
#define ETIMEDOUT WSAETIMEDOUT
|
#define ETIMEDOUT WSAETIMEDOUT
|
||||||
#define ECONNREFUSED WSAECONNREFUSED
|
#define ECONNREFUSED WSAECONNREFUSED
|
||||||
#define ELOOP WSAELOOP
|
#define ELOOP WSAELOOP
|
||||||
|
// #define ENAMETOOLONG WSAENAMETOOLONG
|
||||||
#define EHOSTDOWN WSAEHOSTDOWN
|
#define EHOSTDOWN WSAEHOSTDOWN
|
||||||
#define EHOSTUNREACH WSAEHOSTUNREACH
|
#define EHOSTUNREACH WSAEHOSTUNREACH
|
||||||
|
// #define ENOTEMPTY WSAENOTEMPTY
|
||||||
#define EPROCLIM WSAEPROCLIM
|
#define EPROCLIM WSAEPROCLIM
|
||||||
#define EUSERS WSAEUSERS
|
#define EUSERS WSAEUSERS
|
||||||
#define EDQUOT WSAEDQUOT
|
#define EDQUOT WSAEDQUOT
|
||||||
@@ -1,217 +0,0 @@
|
|||||||
/*
|
|
||||||
* uhub - A tiny ADC p2p connection hub
|
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "uhub.h"
|
|
||||||
|
|
||||||
#include "network/connection.h"
|
|
||||||
|
|
||||||
struct net_backend;
|
|
||||||
struct net_connection;
|
|
||||||
|
|
||||||
struct net_cleanup_handler
|
|
||||||
{
|
|
||||||
size_t num;
|
|
||||||
size_t max;
|
|
||||||
struct net_connection** queue;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct net_backend
|
|
||||||
{
|
|
||||||
struct net_backend_common common;
|
|
||||||
time_t now; /* the time now (used for timeout handling) */
|
|
||||||
struct timeout_queue timeout_queue; /* used for timeout handling */
|
|
||||||
struct net_cleanup_handler* cleaner; /* handler to cleanup connections at a safe point */
|
|
||||||
struct net_backend_handler handler; /* backend event handler */
|
|
||||||
struct net_backend* data; /* backend specific data */
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct net_backend* g_backend;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
|
||||||
extern struct net_backend* net_backend_init_epoll(struct net_backend_handler*, struct net_backend_common*);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_KQUEUE
|
|
||||||
extern struct net_backend* net_backend_init_kqueue(struct net_backend_handler*, struct net_backend_common*);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_SELECT
|
|
||||||
extern struct net_backend* net_backend_init_select(struct net_backend_handler*, struct net_backend_common*);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static net_backend_init_t net_backend_init_funcs[] = {
|
|
||||||
#ifdef USE_EPOLL
|
|
||||||
net_backend_init_epoll,
|
|
||||||
#endif
|
|
||||||
#ifdef USE_KQUEUE
|
|
||||||
net_backend_init_kqueue,
|
|
||||||
#endif
|
|
||||||
#ifdef USE_SELECT
|
|
||||||
net_backend_init_select,
|
|
||||||
#endif
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
int net_backend_init()
|
|
||||||
{
|
|
||||||
size_t n;
|
|
||||||
g_backend = hub_malloc_zero(sizeof(struct net_backend));
|
|
||||||
g_backend->common.num = 0;
|
|
||||||
g_backend->common.max = net_get_max_sockets();
|
|
||||||
g_backend->now = time(0);
|
|
||||||
timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 120); /* FIXME: max 120 secs! */
|
|
||||||
g_backend->cleaner = net_cleanup_initialize(g_backend->common.max);
|
|
||||||
|
|
||||||
for (n = 0; n < sizeof(net_backend_init_funcs); n++)
|
|
||||||
{
|
|
||||||
if (!net_backend_init_funcs[n])
|
|
||||||
break;
|
|
||||||
|
|
||||||
g_backend->data = net_backend_init_funcs[n](&g_backend->handler, &g_backend->common);
|
|
||||||
if (g_backend->data)
|
|
||||||
{
|
|
||||||
LOG_DEBUG("Initialized %s network backend.", g_backend->handler.backend_name());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG_FATAL("Unable to find a suitable network backend");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_backend_shutdown()
|
|
||||||
{
|
|
||||||
g_backend->handler.backend_shutdown(g_backend->data);
|
|
||||||
timeout_queue_shutdown(&g_backend->timeout_queue);
|
|
||||||
net_cleanup_shutdown(g_backend->cleaner);
|
|
||||||
hub_free(g_backend);
|
|
||||||
g_backend = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
|
|
||||||
{
|
|
||||||
con->callback = callback;
|
|
||||||
con->ptr = (void*) ptr;
|
|
||||||
net_con_update(con, events);
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_update(struct net_connection* con, int events)
|
|
||||||
{
|
|
||||||
g_backend->handler.con_mod(g_backend->data, con, events);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct net_connection* net_con_create()
|
|
||||||
{
|
|
||||||
return g_backend->handler.con_create(g_backend->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct timeout_queue* net_backend_get_timeout_queue()
|
|
||||||
{
|
|
||||||
if (!g_backend)
|
|
||||||
return 0;
|
|
||||||
return &g_backend->timeout_queue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process the network backend.
|
|
||||||
*/
|
|
||||||
int net_backend_process()
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now);
|
|
||||||
|
|
||||||
res = g_backend->handler.backend_poll(g_backend->data, secs * 1000);
|
|
||||||
|
|
||||||
g_backend->now = time(0);
|
|
||||||
timeout_queue_process(&g_backend->timeout_queue, g_backend->now);
|
|
||||||
|
|
||||||
if (res == -1)
|
|
||||||
{
|
|
||||||
LOG_WARN("backend error.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_backend->handler.backend_process(g_backend->data, res);
|
|
||||||
|
|
||||||
net_cleanup_process(g_backend->cleaner);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events)
|
|
||||||
{
|
|
||||||
g_backend->handler.con_init(g_backend->data, con, sd, callback, ptr);
|
|
||||||
|
|
||||||
net_set_nonblocking(con->sd, 1);
|
|
||||||
net_set_nosigpipe(con->sd, 1);
|
|
||||||
|
|
||||||
g_backend->handler.con_add(g_backend->data, con, events);
|
|
||||||
g_backend->common.num++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_close(struct net_connection* con)
|
|
||||||
{
|
|
||||||
if (con->flags & NET_CLEANUP)
|
|
||||||
return;
|
|
||||||
|
|
||||||
g_backend->common.num--;
|
|
||||||
net_con_clear_timeout(con);
|
|
||||||
|
|
||||||
g_backend->handler.con_del(g_backend->data, con);
|
|
||||||
|
|
||||||
net_close(con->sd);
|
|
||||||
con->sd = -1;
|
|
||||||
|
|
||||||
net_cleanup_delayed_free(g_backend->cleaner, con);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct net_cleanup_handler* net_cleanup_initialize(size_t max)
|
|
||||||
{
|
|
||||||
struct net_cleanup_handler* handler = (struct net_cleanup_handler*) hub_malloc(sizeof(struct net_cleanup_handler));
|
|
||||||
handler->num = 0;
|
|
||||||
handler->max = max;
|
|
||||||
handler->queue = hub_malloc_zero(sizeof(struct net_connection*) * max);
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_cleanup_shutdown(struct net_cleanup_handler* handler)
|
|
||||||
{
|
|
||||||
hub_free(handler->queue);
|
|
||||||
hub_free(handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_cleanup_delayed_free(struct net_cleanup_handler* handler, struct net_connection* con)
|
|
||||||
{
|
|
||||||
handler->queue[handler->num++] = con;
|
|
||||||
con->flags |= NET_CLEANUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_cleanup_process(struct net_cleanup_handler* handler)
|
|
||||||
{
|
|
||||||
size_t n;
|
|
||||||
for (n = 0; n < handler->num; n++)
|
|
||||||
{
|
|
||||||
struct net_connection* con = handler->queue[n];
|
|
||||||
LOG_TRACE("net_cleanup_process: free: %p", con);
|
|
||||||
hub_free(con);
|
|
||||||
}
|
|
||||||
handler->num = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_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_init();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shutdown the network connection backend.
|
|
||||||
*/
|
|
||||||
extern void net_backend_shutdown();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process the network backend.
|
|
||||||
*/
|
|
||||||
extern int net_backend_process();
|
|
||||||
|
|
||||||
extern struct timeout_queue* net_backend_get_timeout_queue();
|
|
||||||
|
|
||||||
struct net_cleanup_handler* net_cleanup_initialize(size_t max);
|
|
||||||
|
|
||||||
void net_cleanup_shutdown(struct net_cleanup_handler* handler);
|
|
||||||
|
|
||||||
void net_cleanup_delayed_free(struct net_cleanup_handler* handler, struct net_connection* con);
|
|
||||||
|
|
||||||
void net_cleanup_process(struct net_cleanup_handler* handler);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_NETWORK_BACKEND_H */
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* uhub - A tiny ADC p2p connection hub
|
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define NET_WANT_READ NET_EVENT_READ
|
|
||||||
#define NET_WANT_WRITE NET_EVENT_WRITE
|
|
||||||
#define NET_WANT_ACCEPT NET_EVENT_READ
|
|
||||||
#define NET_WANT_SSL_READ 0x0010
|
|
||||||
#define NET_WANT_SSL_WRITE 0x0020
|
|
||||||
#define NET_WANT_SSL_ACCEPT 0x0040
|
|
||||||
#define NET_WANT_SSL_CONNECT 0x0080
|
|
||||||
#define NET_WANT_SSL_X509_LOOKUP 0x0100
|
|
||||||
|
|
||||||
#define NET_CLEANUP 0x8000
|
|
||||||
|
|
||||||
#define NET_CON_STRUCT_BASIC \
|
|
||||||
int sd; /** socket descriptor */ \
|
|
||||||
uint32_t flags; /** Connection flags */ \
|
|
||||||
void* ptr; /** data pointer */ \
|
|
||||||
net_connection_cb callback; /** Callback function */ \
|
|
||||||
struct timeout_evt* timeout; /** timeout event handler */
|
|
||||||
|
|
||||||
#define NET_CON_STRUCT_SSL \
|
|
||||||
SSL* ssl; /** SSL handle */ \
|
|
||||||
uint32_t ssl_state; /** SSL state */ \
|
|
||||||
size_t write_len; /** Length of last SSL_write(), only used if flags is NET_WANT_SSL_READ. */ \
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
#define NET_CON_STRUCT_COMMON \
|
|
||||||
NET_CON_STRUCT_BASIC \
|
|
||||||
NET_CON_STRUCT_SSL
|
|
||||||
#else
|
|
||||||
#define NET_CON_STRUCT_COMMON \
|
|
||||||
NET_CON_STRUCT_BASIC
|
|
||||||
#endif /* SSL_SUPPORT */
|
|
||||||
|
|
||||||
@@ -1,328 +0,0 @@
|
|||||||
/*
|
|
||||||
* uhub - A tiny ADC p2p connection hub
|
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "uhub.h"
|
|
||||||
#include "network/common.h"
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
|
|
||||||
enum uhub_tls_state
|
|
||||||
{
|
|
||||||
tls_st_none,
|
|
||||||
tls_st_error,
|
|
||||||
tls_st_accepting,
|
|
||||||
tls_st_connecting,
|
|
||||||
tls_st_connected,
|
|
||||||
tls_st_disconnecting,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int handle_openssl_error(struct net_connection* con, int ret)
|
|
||||||
{
|
|
||||||
uhub_assert(con);
|
|
||||||
|
|
||||||
int error = SSL_get_error(con->ssl, ret);
|
|
||||||
switch (error)
|
|
||||||
{
|
|
||||||
case SSL_ERROR_ZERO_RETURN:
|
|
||||||
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_ZERO_RETURN", ret, error);
|
|
||||||
con->ssl_state = tls_st_error;
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
case SSL_ERROR_WANT_READ:
|
|
||||||
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_READ", ret, error);
|
|
||||||
con->flags |= NET_WANT_SSL_READ;
|
|
||||||
net_con_update(con, NET_EVENT_READ);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case SSL_ERROR_WANT_WRITE:
|
|
||||||
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_WRITE", ret, error);
|
|
||||||
con->flags |= NET_WANT_SSL_WRITE;
|
|
||||||
net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case SSL_ERROR_SYSCALL:
|
|
||||||
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SYSCALL", ret, error);
|
|
||||||
/* if ret == 0, connection closed, if ret == -1, check with errno */
|
|
||||||
if (ret == 0)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return -net_error();
|
|
||||||
|
|
||||||
case SSL_ERROR_SSL:
|
|
||||||
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SSL", ret, error);
|
|
||||||
/* internal openssl error */
|
|
||||||
con->ssl_state = tls_st_error;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t net_con_ssl_accept(struct net_connection* con)
|
|
||||||
{
|
|
||||||
uhub_assert(con);
|
|
||||||
con->ssl_state = tls_st_accepting;
|
|
||||||
ssize_t ret = SSL_accept(con->ssl);
|
|
||||||
#ifdef NETWORK_DUMP_DEBUG
|
|
||||||
LOG_PROTO("SSL_accept() ret=%d", ret);
|
|
||||||
#endif
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
net_con_update(con, NET_EVENT_READ);
|
|
||||||
con->ssl_state = tls_st_connected;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return handle_openssl_error(con, ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t net_con_ssl_connect(struct net_connection* con)
|
|
||||||
{
|
|
||||||
uhub_assert(con);
|
|
||||||
|
|
||||||
con->ssl_state = tls_st_connecting;
|
|
||||||
ssize_t ret = SSL_connect(con->ssl);
|
|
||||||
#ifdef NETWORK_DUMP_DEBUG
|
|
||||||
LOG_PROTO("SSL_connect() ret=%d", ret);
|
|
||||||
#endif
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
con->ssl_state = tls_st_connected;
|
|
||||||
net_con_update(con, NET_EVENT_READ);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return handle_openssl_error(con, ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, SSL_CTX* ssl_ctx)
|
|
||||||
{
|
|
||||||
uhub_assert(con);
|
|
||||||
SSL* ssl = 0;
|
|
||||||
|
|
||||||
if (ssl_mode == net_con_ssl_mode_server)
|
|
||||||
{
|
|
||||||
ssl = SSL_new(ssl_ctx);
|
|
||||||
SSL_set_fd(ssl, con->sd);
|
|
||||||
net_con_set_ssl(con, ssl);
|
|
||||||
return net_con_ssl_accept(con);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ssl = SSL_new(SSL_CTX_new(TLSv1_method()));
|
|
||||||
SSL_set_fd(ssl, con->sd);
|
|
||||||
net_con_set_ssl(con, ssl);
|
|
||||||
return net_con_ssl_connect(con);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SSL_SUPPORT */
|
|
||||||
|
|
||||||
|
|
||||||
ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
if (!con->ssl)
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL);
|
|
||||||
if (ret == -1)
|
|
||||||
{
|
|
||||||
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
|
|
||||||
return 0;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
con->write_len = len;
|
|
||||||
ret = SSL_write(con->ssl, buf, len);
|
|
||||||
LOG_PROTO("SSL_write(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
|
|
||||||
if (ret <= 0)
|
|
||||||
{
|
|
||||||
return -handle_openssl_error(con, ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
if (!net_con_is_ssl(con))
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
ret = net_recv(con->sd, buf, len, 0);
|
|
||||||
if (ret == -1)
|
|
||||||
{
|
|
||||||
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
|
|
||||||
return 0;
|
|
||||||
return -net_error();
|
|
||||||
}
|
|
||||||
else if (ret == 0)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (con->ssl_state == tls_st_error)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = SSL_read(con->ssl, buf, len);
|
|
||||||
LOG_PROTO("SSL_read(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
net_con_update(con, NET_EVENT_READ);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return -handle_openssl_error(con, ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
|
|
||||||
{
|
|
||||||
int ret = net_recv(con->sd, buf, len, MSG_PEEK);
|
|
||||||
if (ret == -1)
|
|
||||||
{
|
|
||||||
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
|
|
||||||
return 0;
|
|
||||||
return -net_error();
|
|
||||||
}
|
|
||||||
else if (ret == 0)
|
|
||||||
return -1;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
int net_con_is_ssl(struct net_connection* con)
|
|
||||||
{
|
|
||||||
return con->ssl != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSL* net_con_get_ssl(struct net_connection* con)
|
|
||||||
{
|
|
||||||
return con->ssl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_set_ssl(struct net_connection* con, SSL* ssl)
|
|
||||||
{
|
|
||||||
con->ssl = ssl;
|
|
||||||
}
|
|
||||||
#endif /* SSL_SUPPORT */
|
|
||||||
|
|
||||||
int net_con_get_sd(struct net_connection* con)
|
|
||||||
{
|
|
||||||
return con->sd;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* net_con_get_ptr(struct net_connection* con)
|
|
||||||
{
|
|
||||||
return con->ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_destroy(struct net_connection* con)
|
|
||||||
{
|
|
||||||
hub_free(con);
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_callback(struct net_connection* con, int events)
|
|
||||||
{
|
|
||||||
if (con->flags & NET_CLEANUP)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (events == NET_EVENT_TIMEOUT)
|
|
||||||
{
|
|
||||||
LOG_TRACE("net_con_callback(%p, TIMEOUT", con);
|
|
||||||
con->callback(con, events, con->ptr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
if (!con->ssl)
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
con->callback(con, events, con->ptr);
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef NETWORK_DUMP_DEBUG
|
|
||||||
LOG_PROTO("net_con_event: events=%d, con=%p, state=%d", events, con, con->ssl_state);
|
|
||||||
#endif
|
|
||||||
switch (con->ssl_state)
|
|
||||||
{
|
|
||||||
case tls_st_none:
|
|
||||||
con->callback(con, events, con->ptr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case tls_st_error:
|
|
||||||
con->callback(con, NET_EVENT_READ, con->ptr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case tls_st_accepting:
|
|
||||||
if (net_con_ssl_accept(con) < 0)
|
|
||||||
{
|
|
||||||
con->callback(con, NET_EVENT_READ, con->ptr);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case tls_st_connecting:
|
|
||||||
if (net_con_ssl_connect(con) < 0)
|
|
||||||
{
|
|
||||||
con->callback(con, NET_EVENT_READ, con->ptr);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case tls_st_connected:
|
|
||||||
LOG_PROTO("tls_st_connected, events=%s%s, ssl_flags=%s%s", (events & NET_EVENT_READ ? "R" : ""), (events & NET_EVENT_WRITE ? "W" : ""), con->flags & NET_WANT_SSL_READ ? "R" : "", con->flags & NET_WANT_SSL_WRITE ? "W" : "");
|
|
||||||
if (events & NET_EVENT_WRITE && con->flags & NET_WANT_SSL_READ)
|
|
||||||
{
|
|
||||||
con->callback(con, events & NET_EVENT_READ, con->ptr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (events & NET_EVENT_READ && con->flags & NET_WANT_SSL_WRITE)
|
|
||||||
{
|
|
||||||
con->callback(con, events & NET_EVENT_READ, con->ptr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
con->callback(con, events, con->ptr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case tls_st_disconnecting:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_NETWORK_CONNECTION_H
|
|
||||||
#define HAVE_UHUB_NETWORK_CONNECTION_H
|
|
||||||
|
|
||||||
#include "uhub.h"
|
|
||||||
#include "network/common.h"
|
|
||||||
#include "network/backend.h"
|
|
||||||
|
|
||||||
#define NET_EVENT_TIMEOUT 0x0001
|
|
||||||
#define NET_EVENT_READ 0x0002
|
|
||||||
#define NET_EVENT_WRITE 0x0004
|
|
||||||
|
|
||||||
struct net_connection
|
|
||||||
{
|
|
||||||
NET_CON_STRUCT_COMMON
|
|
||||||
};
|
|
||||||
|
|
||||||
extern int net_con_get_sd(struct net_connection* con);
|
|
||||||
extern void* net_con_get_ptr(struct net_connection* con);
|
|
||||||
|
|
||||||
extern struct net_connection* net_con_create();
|
|
||||||
extern void net_con_destroy(struct net_connection*);
|
|
||||||
extern void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events);
|
|
||||||
extern void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events);
|
|
||||||
extern void net_con_update(struct net_connection* con, int events);
|
|
||||||
extern void net_con_callback(struct net_connection* con, int events);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the connection.
|
|
||||||
* This will ensure a connection is closed properly and will generate a NET_EVENT_DESTROYED event which indicates
|
|
||||||
* that the con can safely be deleted (or set to NULL).
|
|
||||||
*/
|
|
||||||
extern void net_con_close(struct net_connection* con);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send data
|
|
||||||
*
|
|
||||||
* @return returns the number of bytes sent.
|
|
||||||
* 0 if no data is sent, and this function should be called again (EWOULDBLOCK/EINTR)
|
|
||||||
* <0 if an error occured, the negative number contains the error code.
|
|
||||||
*/
|
|
||||||
extern ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receive data
|
|
||||||
*
|
|
||||||
* @return returns the number of bytes sent.
|
|
||||||
* 0 if no data is sent, and this function should be called again (EWOULDBLOCK/EINTR)
|
|
||||||
* <0 if an error occured, the negative number contains the error code.
|
|
||||||
*/
|
|
||||||
extern ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receive data without removing them from the recv() buffer.
|
|
||||||
* NOTE: This does not currently work for SSL connections after the SSL handshake has been
|
|
||||||
* performed.
|
|
||||||
*/
|
|
||||||
extern ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set timeout for connetion.
|
|
||||||
*
|
|
||||||
* @param seconds the number of seconds into the future.
|
|
||||||
*/
|
|
||||||
extern void net_con_set_timeout(struct net_connection* con, int seconds);
|
|
||||||
extern void net_con_clear_timeout(struct net_connection* con);
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
/**
|
|
||||||
* Start SSL_accept()
|
|
||||||
*/
|
|
||||||
extern ssize_t net_con_ssl_accept(struct net_connection*);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start SSL_connect()
|
|
||||||
*/
|
|
||||||
extern ssize_t net_con_ssl_connect(struct net_connection*);
|
|
||||||
|
|
||||||
enum net_con_ssl_mode
|
|
||||||
{
|
|
||||||
net_con_ssl_mode_server,
|
|
||||||
net_con_ssl_mode_client,
|
|
||||||
};
|
|
||||||
|
|
||||||
extern ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode, SSL_CTX* ssl_ctx);
|
|
||||||
|
|
||||||
extern int net_con_is_ssl(struct net_connection* con);
|
|
||||||
extern SSL* net_con_get_ssl(struct net_connection* con);
|
|
||||||
extern void net_con_set_ssl(struct net_connection* con, SSL*);
|
|
||||||
#endif /* SSL_SUPPORT */
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_NETWORK_CONNECTION_H */
|
|
||||||
|
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_EPOLL
|
|
||||||
|
|
||||||
#include "network/connection.h"
|
|
||||||
#include "network/common.h"
|
|
||||||
#include "network/backend.h"
|
|
||||||
|
|
||||||
#define EPOLL_EVBUFFER 512
|
|
||||||
|
|
||||||
struct net_connection_epoll
|
|
||||||
{
|
|
||||||
NET_CON_STRUCT_COMMON
|
|
||||||
struct epoll_event ev;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct net_backend_epoll
|
|
||||||
{
|
|
||||||
int epfd;
|
|
||||||
struct net_connection_epoll** conns;
|
|
||||||
struct epoll_event events[EPOLL_EVBUFFER];
|
|
||||||
struct net_backend_common* common;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void net_backend_set_handlers(struct net_backend_handler* handler);
|
|
||||||
|
|
||||||
const char* net_backend_name_epoll()
|
|
||||||
{
|
|
||||||
return "epoll";
|
|
||||||
}
|
|
||||||
|
|
||||||
int net_backend_poll_epoll(struct net_backend* data, int ms)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_backend_process_epoll(struct net_backend* data, int res)
|
|
||||||
{
|
|
||||||
int n, ev;
|
|
||||||
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
|
||||||
for (n = 0; n < res; n++)
|
|
||||||
{
|
|
||||||
struct net_connection_epoll* con = backend->conns[backend->events[n].data.fd];
|
|
||||||
if (con)
|
|
||||||
{
|
|
||||||
ev = 0;
|
|
||||||
if (backend->events[n].events & EPOLLIN) ev |= NET_EVENT_READ;
|
|
||||||
if (backend->events[n].events & EPOLLOUT) ev |= NET_EVENT_WRITE;
|
|
||||||
net_con_callback((struct net_connection*) con, ev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct net_connection* net_con_create_epoll(struct net_backend* data)
|
|
||||||
{
|
|
||||||
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_epoll));
|
|
||||||
con->sd = -1;
|
|
||||||
return con;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_initialize_epoll(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr)
|
|
||||||
{
|
|
||||||
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
|
||||||
con->sd = sd;
|
|
||||||
con->flags = 0;
|
|
||||||
con->callback = callback;
|
|
||||||
con->ev.events = 0;
|
|
||||||
con->ptr = (void*) ptr;
|
|
||||||
con->ev.data.fd = sd;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_backend_add_epoll(struct net_backend* data, struct net_connection* con_, int events)
|
|
||||||
{
|
|
||||||
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
|
||||||
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
|
||||||
|
|
||||||
backend->conns[con->sd] = con;
|
|
||||||
|
|
||||||
if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN;
|
|
||||||
if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT;
|
|
||||||
|
|
||||||
if (epoll_ctl(backend->epfd, EPOLL_CTL_ADD, con->sd, &con->ev) == -1)
|
|
||||||
{
|
|
||||||
LOG_TRACE("epoll_ctl() add failed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_backend_mod_epoll(struct net_backend* data, struct net_connection* con_, int events)
|
|
||||||
{
|
|
||||||
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
|
||||||
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
|
||||||
|
|
||||||
int newev = 0;
|
|
||||||
if (events & NET_EVENT_READ) newev |= EPOLLIN;
|
|
||||||
if (events & NET_EVENT_WRITE) newev |= EPOLLOUT;
|
|
||||||
|
|
||||||
if (newev == con->ev.events)
|
|
||||||
return;
|
|
||||||
|
|
||||||
con->ev.events = newev;
|
|
||||||
if (epoll_ctl(backend->epfd, EPOLL_CTL_MOD, con->sd, &con->ev) == -1)
|
|
||||||
{
|
|
||||||
LOG_TRACE("epoll_ctl() modify failed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_backend_del_epoll(struct net_backend* data, struct net_connection* con_)
|
|
||||||
{
|
|
||||||
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
|
||||||
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
|
||||||
|
|
||||||
backend->conns[con->sd] = 0;
|
|
||||||
|
|
||||||
if (epoll_ctl(backend->epfd, EPOLL_CTL_DEL, con->sd, &con->ev) == -1)
|
|
||||||
{
|
|
||||||
LOG_WARN("epoll_ctl() delete failed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_backend_shutdown_epoll(struct net_backend* data)
|
|
||||||
{
|
|
||||||
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
|
||||||
close(backend->epfd);
|
|
||||||
hub_free(backend->conns);
|
|
||||||
hub_free(backend);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct net_backend* net_backend_init_epoll(struct net_backend_handler* handler, struct net_backend_common* common)
|
|
||||||
{
|
|
||||||
struct net_backend_epoll* backend;
|
|
||||||
|
|
||||||
if (getenv("EVENT_NOEPOLL"))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
backend = hub_malloc_zero(sizeof(struct net_backend_epoll));
|
|
||||||
backend->epfd = epoll_create(common->max);
|
|
||||||
if (backend->epfd == -1)
|
|
||||||
{
|
|
||||||
LOG_WARN("Unable to create epoll socket.");
|
|
||||||
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 */
|
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
/*
|
|
||||||
* uhub - A tiny ADC p2p connection hub
|
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "uhub.h"
|
|
||||||
|
|
||||||
#ifdef USE_KQUEUE
|
|
||||||
|
|
||||||
#include "network/connection.h"
|
|
||||||
#include "network/common.h"
|
|
||||||
#include "network/backend.h"
|
|
||||||
|
|
||||||
#define KQUEUE_EVBUFFER 512
|
|
||||||
|
|
||||||
struct net_connection_kqueue
|
|
||||||
{
|
|
||||||
NET_CON_STRUCT_COMMON
|
|
||||||
struct kevent ev;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct net_backend_kqueue
|
|
||||||
{
|
|
||||||
int kqfd;
|
|
||||||
struct net_connection_kqueue** conns;
|
|
||||||
struct kevent** changes;
|
|
||||||
size_t nchanges;
|
|
||||||
struct kevent events[KQUEUE_EVBUFFER];
|
|
||||||
struct net_backend_common* common;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void net_backend_set_handlers(struct net_backend_handler* handler);
|
|
||||||
|
|
||||||
const char* net_backend_name_kqueue()
|
|
||||||
{
|
|
||||||
return "kqueue";
|
|
||||||
}
|
|
||||||
|
|
||||||
int net_backend_poll_kqueue(struct net_backend* data, int ms)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
struct timespec tspec = { 0, };
|
|
||||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
|
||||||
|
|
||||||
tspec.tv_sec = (ms / 1000);
|
|
||||||
tspec.tv_nsec = ((ms % 1000) * 1000000); /* FIXME: correct? */
|
|
||||||
|
|
||||||
res = kevent(backend->kqfd, *backend->changes, backend->nchanges, backend->events, KQUEUE_EVBUFFER, &tspec);
|
|
||||||
backend->nchanges = 0;
|
|
||||||
|
|
||||||
if (res == -1 && errno == EINTR)
|
|
||||||
return 0;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_backend_process_kqueue(struct net_backend* data, int res)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
|
||||||
|
|
||||||
for (n = 0; n < res; n++)
|
|
||||||
{
|
|
||||||
struct net_connection_kqueue* con = (struct net_connection_kqueue*) backend->events[n].udata;
|
|
||||||
int ev = 0;
|
|
||||||
if (backend->events[n].filter & EVFILT_READ) ev |= NET_EVENT_READ;
|
|
||||||
if (backend->events[n].filter & EVFILT_WRITE) ev |= NET_EVENT_WRITE;
|
|
||||||
net_con_callback((struct net_connection*) con, ev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct net_connection* net_con_create_kqueue(struct net_backend* data)
|
|
||||||
{
|
|
||||||
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_kqueue));
|
|
||||||
con->sd = -1;
|
|
||||||
return con;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_initialize_kqueue(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr)
|
|
||||||
{
|
|
||||||
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
|
||||||
con->sd = sd;
|
|
||||||
con->flags = 0;
|
|
||||||
con->callback = callback;
|
|
||||||
con->ptr = (void*) ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_backend_add_kqueue(struct net_backend* data, struct net_connection* con_, int events)
|
|
||||||
{
|
|
||||||
short filter = 0;
|
|
||||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
|
||||||
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
|
||||||
if (events & NET_EVENT_READ) filter |= EVFILT_READ;
|
|
||||||
if (events & NET_EVENT_WRITE) filter |= EVFILT_READ;
|
|
||||||
EV_SET(&con->ev, con->sd, filter, EV_ADD, 0, 0, con);
|
|
||||||
backend->changes[backend->nchanges++] = &con->ev;
|
|
||||||
backend->conns[con->sd] = con;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_backend_mod_kqueue(struct net_backend* data, struct net_connection* con_, int events)
|
|
||||||
{
|
|
||||||
short filter = 0;
|
|
||||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
|
||||||
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
|
||||||
|
|
||||||
if (events & NET_EVENT_READ) filter |= EVFILT_READ;
|
|
||||||
if (events & NET_EVENT_WRITE) filter |= EVFILT_READ;
|
|
||||||
|
|
||||||
if (filter == con->ev.filter)
|
|
||||||
return;
|
|
||||||
|
|
||||||
EV_SET(&con->ev, con->sd, filter, EV_ADD, 0, 0, con);
|
|
||||||
backend->changes[backend->nchanges++] = &con->ev;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_backend_del_kqueue(struct net_backend* data, struct net_connection* con_)
|
|
||||||
{
|
|
||||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
|
||||||
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
|
||||||
|
|
||||||
backend->conns[con->sd] = 0;
|
|
||||||
|
|
||||||
/* No need to remove it from the kqueue filter, the kqueue man page says
|
|
||||||
it is automatically removed when the descriptor is closed. */
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_backend_shutdown_kqueue(struct net_backend* data)
|
|
||||||
{
|
|
||||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
|
||||||
close(backend->kqfd);
|
|
||||||
hub_free(backend->conns);
|
|
||||||
hub_free(backend->changes);
|
|
||||||
hub_free(backend);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct net_backend* net_backend_init_kqueue(struct net_backend_handler* handler, struct net_backend_common* common)
|
|
||||||
{
|
|
||||||
struct net_backend_kqueue* backend;
|
|
||||||
|
|
||||||
if (getenv("EVENT_NOKQUEUE"))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
backend = hub_malloc_zero(sizeof(struct net_backend_kqueue));
|
|
||||||
backend->kqfd = kqueue();
|
|
||||||
if (backend->kqfd == -1)
|
|
||||||
{
|
|
||||||
LOG_WARN("Unable to create kqueue socket.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
backend->conns = hub_malloc_zero(sizeof(struct net_connection_kqueue*) * common->max);
|
|
||||||
backend->conns = hub_malloc_zero(sizeof(struct net_connection_kqueue*) * common->max);
|
|
||||||
backend->changes = hub_malloc_zero(sizeof(struct kevent*) * common->max);
|
|
||||||
backend->common = common;
|
|
||||||
|
|
||||||
net_backend_set_handlers(handler);
|
|
||||||
return (struct net_backend*) backend;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void net_backend_set_handlers(struct net_backend_handler* handler)
|
|
||||||
{
|
|
||||||
handler->backend_name = net_backend_name_kqueue;
|
|
||||||
handler->backend_poll = net_backend_poll_kqueue;
|
|
||||||
handler->backend_process = net_backend_process_kqueue;
|
|
||||||
handler->backend_shutdown = net_backend_shutdown_kqueue;
|
|
||||||
handler->con_create = net_con_create_kqueue;
|
|
||||||
handler->con_init = net_con_initialize_kqueue;
|
|
||||||
handler->con_add = net_con_backend_add_kqueue;
|
|
||||||
handler->con_mod = net_con_backend_mod_kqueue;
|
|
||||||
handler->con_del = net_con_backend_del_kqueue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* USE_KQUEUE */
|
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
/*
|
|
||||||
* uhub - A tiny ADC p2p connection hub
|
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "uhub.h"
|
|
||||||
|
|
||||||
#ifdef USE_SELECT
|
|
||||||
|
|
||||||
#include "network/connection.h"
|
|
||||||
#include "network/common.h"
|
|
||||||
#include "network/backend.h"
|
|
||||||
|
|
||||||
struct net_connection_select
|
|
||||||
{
|
|
||||||
NET_CON_STRUCT_COMMON
|
|
||||||
};
|
|
||||||
|
|
||||||
struct net_backend_select
|
|
||||||
{
|
|
||||||
struct net_connection_select** conns;
|
|
||||||
fd_set rfds;
|
|
||||||
fd_set wfds;
|
|
||||||
int maxfd;
|
|
||||||
struct net_backend_common* common;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void net_backend_set_handlers(struct net_backend_handler* handler);
|
|
||||||
|
|
||||||
const char* net_backend_name_select()
|
|
||||||
{
|
|
||||||
return "select";
|
|
||||||
}
|
|
||||||
|
|
||||||
int net_backend_poll_select(struct net_backend* data, int ms)
|
|
||||||
{
|
|
||||||
int found, res, n;
|
|
||||||
struct timeval tval;
|
|
||||||
struct net_backend_select* backend = (struct net_backend_select*) data;
|
|
||||||
|
|
||||||
tval.tv_sec = ms / 1000;
|
|
||||||
tval.tv_usec = ((ms % 1000) * 1000); // FIXME: correct?
|
|
||||||
|
|
||||||
FD_ZERO(&backend->rfds);
|
|
||||||
FD_ZERO(&backend->wfds);
|
|
||||||
|
|
||||||
backend->maxfd = -1;
|
|
||||||
for (n = 0, found = 0; found < backend->common->num && n < backend->common->max; n++)
|
|
||||||
{
|
|
||||||
struct net_connection_select* con = backend->conns[n];
|
|
||||||
if (con)
|
|
||||||
{
|
|
||||||
if (con->flags & NET_EVENT_READ) FD_SET(con->sd, &backend->rfds);
|
|
||||||
if (con->flags & NET_EVENT_WRITE) FD_SET(con->sd, &backend->wfds);
|
|
||||||
found++;
|
|
||||||
backend->maxfd = con->sd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
backend->maxfd++;
|
|
||||||
|
|
||||||
res = select(backend->maxfd, &backend->rfds, &backend->wfds, 0, &tval);
|
|
||||||
|
|
||||||
if (res == -1 && errno == EINTR)
|
|
||||||
return 0;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_backend_process_select(struct net_backend* data, int res)
|
|
||||||
{
|
|
||||||
int n, found;
|
|
||||||
struct net_backend_select* backend = (struct net_backend_select*) data;
|
|
||||||
for (n = 0, found = 0; found < res && n < backend->maxfd; n++)
|
|
||||||
{
|
|
||||||
struct net_connection_select* con = backend->conns[n];
|
|
||||||
if (con)
|
|
||||||
{
|
|
||||||
int ev = 0;
|
|
||||||
if (FD_ISSET(con->sd, &backend->rfds)) ev |= NET_EVENT_READ;
|
|
||||||
if (FD_ISSET(con->sd, &backend->wfds)) ev |= NET_EVENT_WRITE;
|
|
||||||
|
|
||||||
if (ev)
|
|
||||||
{
|
|
||||||
net_con_callback((struct net_connection*) con, ev);
|
|
||||||
found++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct net_connection* net_con_create_select(struct net_backend* data)
|
|
||||||
{
|
|
||||||
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_select));
|
|
||||||
con->sd = -1;
|
|
||||||
return con;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_initialize_select(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr)
|
|
||||||
{
|
|
||||||
struct net_connection_select* con = (struct net_connection_select*) con_;
|
|
||||||
con->sd = sd;
|
|
||||||
con->flags = 0;
|
|
||||||
con->callback = callback;
|
|
||||||
con->ptr = (void*) ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_backend_add_select(struct net_backend* data, struct net_connection* con, int events)
|
|
||||||
{
|
|
||||||
struct net_backend_select* backend = (struct net_backend_select*) data;
|
|
||||||
backend->conns[con->sd] = (struct net_connection_select*) con;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_backend_mod_select(struct net_backend* data, struct net_connection* con, int events)
|
|
||||||
{
|
|
||||||
con->flags |= (events & (NET_EVENT_READ | NET_EVENT_WRITE));;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_backend_del_select(struct net_backend* data, struct net_connection* con)
|
|
||||||
{
|
|
||||||
struct net_backend_select* backend = (struct net_backend_select*) data;
|
|
||||||
backend->conns[con->sd] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_backend_shutdown_select(struct net_backend* data)
|
|
||||||
{
|
|
||||||
struct net_backend_select* backend = (struct net_backend_select*) data;
|
|
||||||
hub_free(backend->conns);
|
|
||||||
hub_free(backend);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct net_backend* net_backend_init_select(struct net_backend_handler* handler, struct net_backend_common* common)
|
|
||||||
{
|
|
||||||
struct net_backend_select* backend;
|
|
||||||
|
|
||||||
if (getenv("EVENT_NOSELECT"))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
backend = hub_malloc_zero(sizeof(struct net_backend_select));
|
|
||||||
FD_ZERO(&backend->rfds);
|
|
||||||
FD_ZERO(&backend->wfds);
|
|
||||||
backend->conns = hub_malloc_zero(sizeof(struct net_connection_select*) * common->max);
|
|
||||||
backend->common = common;
|
|
||||||
net_backend_set_handlers(handler);
|
|
||||||
return (struct net_backend*) backend;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void net_backend_set_handlers(struct net_backend_handler* handler)
|
|
||||||
{
|
|
||||||
handler->backend_name = net_backend_name_select;
|
|
||||||
handler->backend_poll = net_backend_poll_select;
|
|
||||||
handler->backend_process = net_backend_process_select;
|
|
||||||
handler->backend_shutdown = net_backend_shutdown_select;
|
|
||||||
handler->con_create = net_con_create_select;
|
|
||||||
handler->con_init = net_con_initialize_select;
|
|
||||||
handler->con_add = net_con_backend_add_select;
|
|
||||||
handler->con_mod = net_con_backend_mod_select;
|
|
||||||
handler->con_del = net_con_backend_del_select;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* USE_SELECT */
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 wtimeout_evtith this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "uhub.h"
|
|
||||||
|
|
||||||
void timeout_evt_initialize(struct timeout_evt* t, timeout_evt_cb cb, void* ptr)
|
|
||||||
{
|
|
||||||
t->callback = cb;
|
|
||||||
t->ptr = ptr;
|
|
||||||
t->prev = 0;
|
|
||||||
t->next = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void timeout_evt_reset(struct timeout_evt* t)
|
|
||||||
{
|
|
||||||
t->prev = 0;
|
|
||||||
t->next = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int timeout_evt_is_scheduled(struct timeout_evt* t)
|
|
||||||
{
|
|
||||||
return t->prev != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void timeout_queue_initialize(struct timeout_queue* t, time_t now, size_t max)
|
|
||||||
{
|
|
||||||
t->last = now;
|
|
||||||
t->max = max;
|
|
||||||
t->events = hub_malloc_zero(max * sizeof(struct timeout_evt*));
|
|
||||||
}
|
|
||||||
|
|
||||||
void timeout_queue_shutdown(struct timeout_queue* t)
|
|
||||||
{
|
|
||||||
hub_free(t->events);
|
|
||||||
t->events = 0;
|
|
||||||
t->max = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t timeout_queue_process(struct timeout_queue* t, time_t now)
|
|
||||||
{
|
|
||||||
size_t pos = t->last;
|
|
||||||
size_t events = 0;
|
|
||||||
struct timeout_evt* evt = 0;
|
|
||||||
t->last = now;
|
|
||||||
for (; pos <= now; pos++)
|
|
||||||
{
|
|
||||||
while ((evt = t->events[pos % t->max]))
|
|
||||||
{
|
|
||||||
timeout_queue_remove(t, evt);
|
|
||||||
evt->callback(evt);
|
|
||||||
events++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return events;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t timeout_queue_get_next_timeout(struct timeout_queue* t, time_t now)
|
|
||||||
{
|
|
||||||
size_t seconds = 0;
|
|
||||||
while (t->events[(now + seconds) % t->max] == NULL && seconds < t->max)
|
|
||||||
{
|
|
||||||
seconds++;
|
|
||||||
}
|
|
||||||
if (seconds == 0)
|
|
||||||
return 1;
|
|
||||||
return seconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds)
|
|
||||||
{
|
|
||||||
struct timeout_evt* first;
|
|
||||||
size_t pos = ((t->last + seconds) % t->max);
|
|
||||||
evt->timestamp = t->last + seconds;
|
|
||||||
evt->next = 0;
|
|
||||||
|
|
||||||
first = t->events[pos];
|
|
||||||
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
uhub_assert(first->timestamp == evt->timestamp);
|
|
||||||
first->prev->next = evt;
|
|
||||||
evt->prev = first->prev;
|
|
||||||
first->prev = evt;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
t->events[pos] = evt;
|
|
||||||
evt->prev = evt;
|
|
||||||
}
|
|
||||||
evt->next = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void timeout_queue_remove(struct timeout_queue* t, struct timeout_evt* evt)
|
|
||||||
{
|
|
||||||
size_t pos = (evt->timestamp % t->max);
|
|
||||||
struct timeout_evt* first = t->events[pos];
|
|
||||||
|
|
||||||
if (!first || !evt->prev)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (first == evt)
|
|
||||||
{
|
|
||||||
if (first->prev != first)
|
|
||||||
{
|
|
||||||
t->events[pos] = first->next;
|
|
||||||
t->events[pos]->prev = evt->prev;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
t->events[pos] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (evt == first->prev)
|
|
||||||
{
|
|
||||||
first->prev = evt->prev;
|
|
||||||
evt->prev->next = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
evt->prev->next = evt->next;
|
|
||||||
evt->next->prev = evt->prev;
|
|
||||||
}
|
|
||||||
timeout_evt_reset(evt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void timeout_queue_reschedule(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds)
|
|
||||||
{
|
|
||||||
if (timeout_evt_is_scheduled(evt))
|
|
||||||
timeout_queue_remove(t, evt);
|
|
||||||
timeout_queue_insert(t, evt, seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_TIMEOUT_HANDLER_H
|
|
||||||
#define HAVE_UHUB_TIMEOUT_HANDLER_H
|
|
||||||
|
|
||||||
struct timeout_evt;
|
|
||||||
struct timeout_queue;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_TIMEOUT_HANDLER_H */
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* uhub - A tiny ADC p2p connection hub
|
|
||||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "uhub.h"
|
|
||||||
#include "network/connection.h"
|
|
||||||
|
|
||||||
static void timeout_callback(struct timeout_evt* evt)
|
|
||||||
{
|
|
||||||
net_con_callback((struct net_connection*) evt->ptr, NET_EVENT_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_set_timeout(struct net_connection* con, int seconds)
|
|
||||||
{
|
|
||||||
if (!con->timeout)
|
|
||||||
{
|
|
||||||
con->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
|
|
||||||
timeout_evt_initialize(con->timeout, timeout_callback, con);
|
|
||||||
timeout_queue_insert(net_backend_get_timeout_queue(), con->timeout, seconds);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
timeout_queue_reschedule(net_backend_get_timeout_queue(), con->timeout, seconds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_clear_timeout(struct net_connection* con)
|
|
||||||
{
|
|
||||||
if (con->timeout && timeout_evt_is_scheduled(con->timeout))
|
|
||||||
{
|
|
||||||
timeout_queue_remove(net_backend_get_timeout_queue(), con->timeout);
|
|
||||||
hub_free(con->timeout);
|
|
||||||
con->timeout = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
52
src/plugin.h
Normal file
52
src/plugin.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef void (*plugin_event_startup)(struct hub*);
|
||||||
|
typedef void (*plugin_event_shutdown)(struct hub*);
|
||||||
|
typedef void (*plugin_event_user_login)(struct hub*, struct user*);
|
||||||
|
typedef void (*plugin_event_user_logout)(struct hub*, struct user*);
|
||||||
|
typedef int (*plugin_event_connect)(struct hub*, struct ip_addr_encap);
|
||||||
|
typedef void (*plugin_event_disconnect)(struct hub*, struct user*);
|
||||||
|
typedef int (*plugin_event_message)(struct hub*, struct user*, struct adc_message*);
|
||||||
|
typedef void (*plugin_event_support)(struct hub*, struct user*, int);
|
||||||
|
|
||||||
|
struct uhub_plugin
|
||||||
|
{
|
||||||
|
/** Starting the hub */
|
||||||
|
plugin_event_startup evt_startup;
|
||||||
|
|
||||||
|
/** Shutting down the hub */
|
||||||
|
plugin_event_shutdown evt_shutdown;
|
||||||
|
|
||||||
|
/** Someone connected to the hub (we only have IP at this point). */
|
||||||
|
plugin_event_connect evt_connect;
|
||||||
|
|
||||||
|
/** Someone disconnected from the hub (but was not successfully logged in). */
|
||||||
|
plugin_event_disconnect evt_disconnect;
|
||||||
|
|
||||||
|
/** A client sent a message about which protocol extensions it supports */
|
||||||
|
plugin_event_support evt_support;
|
||||||
|
|
||||||
|
/** A client was successfully logged in to the hub */
|
||||||
|
plugin_event_user_login evt_login;
|
||||||
|
|
||||||
|
/** A client (previously logged in) has disconnected. */
|
||||||
|
plugin_event_user_logout evt_logout;
|
||||||
|
};
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user