Compare commits
47 Commits
event_queu
...
0.2.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8af965c0ca | ||
|
|
b3d3dcdb44 | ||
|
|
cb6190c5b4 | ||
|
|
82ad62602d | ||
|
|
6d34bdd7e2 | ||
|
|
c2832e59c0 | ||
|
|
cf23c82c16 | ||
|
|
8bf0fd424a | ||
|
|
8f8284eb29 | ||
|
|
015c3368bd | ||
|
|
9186b441aa | ||
|
|
74af392e80 | ||
|
|
3a270564d2 | ||
|
|
f0938e8afa | ||
|
|
156c137237 | ||
|
|
7aeb8651ba | ||
|
|
ab4eb6db3d | ||
|
|
13a8700554 | ||
|
|
5d5dda2f9b | ||
|
|
95b741bb5e | ||
|
|
90abf64e3a | ||
|
|
e9915df87c | ||
|
|
408829e330 | ||
|
|
1a1b5bdb38 | ||
|
|
abedec692a | ||
|
|
7738baf38e | ||
|
|
3c4c52d0f9 | ||
|
|
76588fb1bd | ||
|
|
f9e95ec582 | ||
|
|
7985d4fed0 | ||
|
|
77343d3c21 | ||
|
|
f8d5b72a89 | ||
|
|
cf2994b570 | ||
|
|
7a9d40d8dd | ||
|
|
b1f84b5b4a | ||
|
|
998c6c36ce | ||
|
|
4112b8111a | ||
|
|
1929f2fae7 | ||
|
|
77e41371b5 | ||
|
|
0266c8bb9c | ||
|
|
5e3eabb677 | ||
|
|
669ab14022 | ||
|
|
1d491055c5 | ||
|
|
08351ea8e7 | ||
|
|
e2ac690164 | ||
|
|
3bb563b432 | ||
|
|
e10582fec2 |
15
ChangeLog
15
ChangeLog
@@ -1,4 +1,19 @@
|
||||
0.2.8:
|
||||
- Fix bug #13: getsockname() failure, use sockaddr from accept() instead.
|
||||
- Fix bug #10: Improve logging, ensure logs are machine readable.
|
||||
- Fix bug #12: asserts in adc_msg_parse -> enabled strict utf8 parsing.
|
||||
|
||||
|
||||
0.2.7:
|
||||
- Fixed a nasty crash (bug #11), Thanks Toast for finding it.
|
||||
- Fix bug #9 - net_get_peer_address() failure on CentOS/Xen configurations.
|
||||
- Write a log message if an operator reloads the config file.
|
||||
- Don't print OK or ERROR when using '-s' or '-S' show the configuration.
|
||||
- Cleanup credential string handling
|
||||
- Made sure "!help" only display accessible commands.
|
||||
- Cleanup in-hub command parsing
|
||||
- Fix a possible crash if multiple INF messages are sent during login.
|
||||
- Rewrote the mainloop to not use a timer.
|
||||
|
||||
|
||||
0.2.6:
|
||||
|
||||
@@ -32,7 +32,7 @@ BIN_EXT ?= .exe
|
||||
else
|
||||
DESTDIR ?= /
|
||||
UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub
|
||||
UHUB_PREFIX ?= $(DESTDIR)/usr/
|
||||
UHUB_PREFIX ?= $(DESTDIR)/usr/local
|
||||
CFLAGS += -I/usr/local/include
|
||||
LDFLAGS += -L/usr/local/lib
|
||||
BIN_EXT ?=
|
||||
|
||||
@@ -6,25 +6,30 @@ else
|
||||
HOST_MACHINE=`uname -m | tr [:upper:] [:lower:] | sed s/i686/i386/ | sed s/x86_64/amd64/ | sed s/ppc64/powerpc/`
|
||||
fi
|
||||
|
||||
BINSUFFIX=
|
||||
MAKEARGS=
|
||||
MAKE=make
|
||||
WANTZIP=0
|
||||
|
||||
if [ "${HOST_SYSTEM}" = "mingw32_nt-5.1" ]; then
|
||||
HOST_SYSTEM=win32
|
||||
BINARY=uhub.exe
|
||||
BINSUFFIX=.exe
|
||||
WANTZIP=1
|
||||
else
|
||||
WANTZIP=0
|
||||
BINARY=uhub
|
||||
MAKEARGS="USE_BIGENDIAN=NO"
|
||||
fi
|
||||
|
||||
BINARY=uhub${BINSUFFIX}
|
||||
|
||||
if [ "${HOST_SYSTEM}" = "freebsd" ]; then
|
||||
MAKE=gmake
|
||||
fi
|
||||
|
||||
VERSION=`grep define\ VERSION version.h | cut -f 3 -d " " | tr -d [=\"=]`
|
||||
SNAPSHOT=`date '+%Y%m%d'`
|
||||
PACKAGE=uhub-${VERSION}
|
||||
PACKAGE_SRC=${PACKAGE}-src
|
||||
PACKAGE_BIN=${PACKAGE}-${HOST_SYSTEM}-${HOST_MACHINE}
|
||||
|
||||
URL_ARCHIVE='build-archive:~/uhub/'
|
||||
URL_PUBLISH='domeneshop:~/www/downloads/uhub/'
|
||||
URL_SNAPSHOT='domeneshop:~/www/downloads/uhub/snapshots/'
|
||||
ARCHIVE='build-archive:~/www/downloads/uhub/'
|
||||
|
||||
function export_source_directory
|
||||
{
|
||||
@@ -51,15 +56,28 @@ function package_zips
|
||||
gzip -c -9 $1.tar > $1.tar.gz
|
||||
bzip2 -c -9 $1.tar > $1.tar.bz2
|
||||
rm -f $1.tar
|
||||
zip -q -9 -r $1.zip $2
|
||||
|
||||
if [ $WANTZIP -eq 1 ]; then
|
||||
zip -q -9 -r $1.zip $2
|
||||
fi
|
||||
}
|
||||
|
||||
function export_sources
|
||||
{
|
||||
export_source_directory
|
||||
make autotest.c && cp autotest.c ${PACKAGE}/autotest.c
|
||||
rm -Rf ${PACKAGE}/admin
|
||||
if [ ! -d ${PACKAGE} ]; then
|
||||
export_source_directory
|
||||
fi
|
||||
|
||||
cd ${PACKAGE}
|
||||
${MAKE} ${MAKEARGS} autotest.c
|
||||
cd ..
|
||||
|
||||
if [ ! -f ${PACKAGE}/autotest.c ]; then
|
||||
echo "Unable to create autotest.c, aborting..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -Rf ${PACKAGE}/admin
|
||||
package_zips ${PACKAGE_SRC} ${PACKAGE}
|
||||
|
||||
rm -Rf ${PACKAGE};
|
||||
@@ -68,28 +86,51 @@ function export_sources
|
||||
|
||||
function export_binaries
|
||||
{
|
||||
export_source_directory
|
||||
if [ ! -d ${PACKAGE} ]; then
|
||||
export_source_directory
|
||||
fi
|
||||
|
||||
cd ${PACKAGE}
|
||||
${MAKE} ${MAKEARGS} RELEASE=YES
|
||||
cd ..
|
||||
|
||||
if [ ! -x ${PACKAGE}/${BINARY} ]; then
|
||||
echo "Packaging failed, no binary found..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -Rf ${PACKAGE}/admin
|
||||
rm -Rf ${PACKAGE}/autotest
|
||||
rm -Rf ${PACKAGE}/src
|
||||
rm -Rf ${PACKAGE}/debian
|
||||
rm -f ${PACKAGE}/autotest.c
|
||||
rm -f ${PACKAGE}/*akefile
|
||||
rm -f ${PACKAGE}/version.h
|
||||
rm -f ${PACKAGE}/doc/Doxyfile
|
||||
rm -f ${PACKAGE}/doc/uhub.dot
|
||||
|
||||
make
|
||||
|
||||
if [ -x ${BINARY} ]; then
|
||||
cp ${BINARY} ${PACKAGE}
|
||||
else
|
||||
echo "No binary found!"
|
||||
exit 1
|
||||
fi
|
||||
rm -f ${PACKAGE}/libuhub*
|
||||
|
||||
package_zips ${PACKAGE_BIN} ${PACKAGE}
|
||||
|
||||
rm -Rf ${PACKAGE};
|
||||
}
|
||||
|
||||
function upload_pkg
|
||||
{
|
||||
if [ -f $1 ]; then
|
||||
scp $1 ${ARCHIVE}
|
||||
fi
|
||||
}
|
||||
|
||||
function upload_packages
|
||||
{
|
||||
upload_pkg ${PACKAGE_SRC}.tar.gz
|
||||
upload_pkg ${PACKAGE_SRC}.tar.bz2
|
||||
upload_pkg ${PACKAGE_SRC}.zip
|
||||
upload_pkg ChangeLog-${VERSION}
|
||||
upload_pkg ${PACKAGE_BIN}.tar.gz
|
||||
upload_pkg ${PACKAGE_BIN}.tar.bz2
|
||||
upload_pkg ${PACKAGE_BIN}.zip
|
||||
}
|
||||
|
||||
|
||||
|
||||
3
admin/export.sh
Executable file
3
admin/export.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
. admin/common.sh
|
||||
export_source_directory
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# set -x
|
||||
|
||||
ME=`dirname $0`
|
||||
. ${ME}/common.sh
|
||||
|
||||
# Git Export
|
||||
export_sources
|
||||
export_binaries
|
||||
|
||||
3
admin/release_binaries.sh
Executable file
3
admin/release_binaries.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
. admin/common.sh
|
||||
export_binaries
|
||||
4
admin/release_sources.sh
Executable file
4
admin/release_sources.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
. admin/common.sh
|
||||
WANTZIP=1
|
||||
export_sources
|
||||
26
admin/setup_archive.sh
Executable file
26
admin/setup_archive.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
PUB="${HOME}/.ssh/id_rsa.pub"
|
||||
CFG="${HOME}/.ssh/config"
|
||||
|
||||
if [ ! "`grep build-archive ${CFG}`" ]; then
|
||||
echo "Updating ssh config (${CFG})..."
|
||||
cat >> ${CFG} <<EOF
|
||||
|
||||
Host build-archive
|
||||
ForwardX11 no
|
||||
HostName login.domeneshop.no
|
||||
User extatic
|
||||
EOF
|
||||
else
|
||||
echo "ssh config seems OK (${CFG})"
|
||||
fi
|
||||
|
||||
if [ ! -f ${PUB} ]; then
|
||||
echo "No id_rsa.pub - run ssh-keygen"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Copying public key (${PUB})..."
|
||||
cat ${PUB} | ssh build-archive "cat >> .ssh/authorized_keys"
|
||||
|
||||
3
admin/upload.sh
Executable file
3
admin/upload.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
. admin/common.sh
|
||||
upload_packages
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
static struct event_queue* eq;
|
||||
static int eq_val;
|
||||
struct event* libevent_handle;
|
||||
|
||||
static void eq_callback(void* callback_data, struct event_data* event_data)
|
||||
{
|
||||
@@ -17,8 +16,6 @@ EXO_TEST(eventqueue_init_1, {
|
||||
|
||||
EXO_TEST(eventqueue_init_2, {
|
||||
/* hack */
|
||||
libevent_handle = eq->event;
|
||||
eq->event = 0;
|
||||
return eq->callback_data == &eq_val && eq->callback == eq_callback && eq->q1 && eq->q2 && !eq->locked;
|
||||
});
|
||||
|
||||
@@ -81,7 +78,6 @@ EXO_TEST(eventqueue_size_4, {
|
||||
});
|
||||
|
||||
EXO_TEST(eventqueue_shutdown_1, {
|
||||
eq->event = libevent_handle;
|
||||
event_queue_shutdown(eq);
|
||||
return 1;
|
||||
});
|
||||
|
||||
@@ -144,12 +144,29 @@ EXO_TEST(adc_message_parse_20, {
|
||||
return ok;
|
||||
});
|
||||
|
||||
|
||||
EXO_TEST(adc_message_parse_21, {
|
||||
struct adc_message* msg = adc_msg_parse_verify(g_user, "EMSG AAAC AAAB Hello\\sthere!\n", 29);
|
||||
return msg == NULL;
|
||||
});
|
||||
|
||||
EXO_TEST(adc_message_parse_22, {
|
||||
struct adc_message* msg = adc_msg_parse_verify(g_user, "\n", 0);
|
||||
return msg == NULL;
|
||||
});
|
||||
|
||||
EXO_TEST(adc_message_parse_23, {
|
||||
struct adc_message* msg = adc_msg_parse_verify(g_user, "\r\n", 1);
|
||||
return msg == NULL;
|
||||
});
|
||||
|
||||
EXO_TEST(adc_message_parse_24, {
|
||||
struct adc_message* msg = adc_msg_parse_verify(g_user, "EMSG AAAC\0AAAB Hello\\sthere!\n", 29);
|
||||
return msg == NULL;
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
EXO_TEST(adc_message_add_arg_1, {
|
||||
struct adc_message* msg = adc_msg_create(test_string1);
|
||||
adc_msg_add_argument(msg, "XXwtf?");
|
||||
|
||||
@@ -100,4 +100,12 @@ EXO_TEST(utf8_valid_3, { return is_valid_utf8("0123456789"); });
|
||||
EXO_TEST(utf8_valid_4, { return is_valid_utf8( (char[]) { 0x65, 0x00} ); });
|
||||
EXO_TEST(utf8_valid_5, { return !is_valid_utf8( (char[]) { 0xD8, 0x00} ); });
|
||||
|
||||
EXO_TEST(utf8_valid_6, { return is_valid_utf8( (char[]) { 0x24, 0x00} ); });
|
||||
EXO_TEST(utf8_valid_7, { return !is_valid_utf8( (char[]) { 0xC2, 0x24, 0x00} ); });
|
||||
EXO_TEST(utf8_valid_8, { return is_valid_utf8( (char[]) { 0xC2, 0xA2, 0x00} ); });
|
||||
EXO_TEST(utf8_valid_9, { return is_valid_utf8( (char[]) { 0xE2, 0x82, 0xAC, 0x00} ); });
|
||||
EXO_TEST(utf8_valid_10, { return !is_valid_utf8( (char[]) { 0xC2, 0x32, 0x00} ); });
|
||||
EXO_TEST(utf8_valid_11, { return !is_valid_utf8( (char[]) { 0xE2, 0x82, 0x32, 0x00} ); });
|
||||
EXO_TEST(utf8_valid_12, { return !is_valid_utf8( (char[]) { 0xE2, 0x32, 0x82, 0x00} ); });
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#define ACL_ADD_BOOL(S, L) do { ret = check_cmd_bool(S, L, line, line_count); if (ret != 0) return ret; } while(0)
|
||||
#define ACL_ADD_ADDR(S, L) do { ret = check_cmd_addr(S, L, line, line_count); if (ret != 0) return ret; } while(0)
|
||||
|
||||
static const char* get_user_credential_string(enum user_credentials cred)
|
||||
const char* get_user_credential_string(enum user_credentials cred)
|
||||
{
|
||||
switch (cred)
|
||||
{
|
||||
|
||||
@@ -48,6 +48,8 @@ enum user_credentials
|
||||
cred_link, /**<<< "User is a link (not used currently)" */
|
||||
};
|
||||
|
||||
const char* get_user_credential_string(enum user_credentials cred);
|
||||
|
||||
struct user_access_info
|
||||
{
|
||||
char* username; /* name of user, cid or IP range */
|
||||
|
||||
238
src/commands.c
238
src/commands.c
@@ -19,165 +19,175 @@
|
||||
|
||||
#include "uhub.h"
|
||||
|
||||
static int command_access_denied(struct user* user)
|
||||
typedef int (*command_handler)(struct user* user, const char* message);
|
||||
|
||||
struct commands_handler
|
||||
{
|
||||
struct adc_message* command;
|
||||
char* buffer = adc_msg_escape("Access denied.");
|
||||
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||
adc_msg_add_argument(command, buffer);
|
||||
route_to_user(user, command);
|
||||
adc_msg_free(command);
|
||||
hub_free(buffer);
|
||||
return 0;
|
||||
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 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 user* user, const char* command)
|
||||
{
|
||||
char temp[64];
|
||||
snprintf(temp, 64, "*** Access denied: \"%s\"", command);
|
||||
send_message(user, temp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int command_stats(struct user* user, const char* message)
|
||||
{
|
||||
struct adc_message* command;
|
||||
|
||||
if (user->credentials < cred_super)
|
||||
return command_access_denied(user);
|
||||
|
||||
char temp[128];
|
||||
|
||||
snprintf(temp, 128, "*** Stats: %zu users, peak: %zu. Network (up/down): %d/%d KB/s, peak: %d/%d KB/s",
|
||||
char temp[128];
|
||||
snprintf(temp, 128, "*** Stats: %zu users, peak: %zu. Network (up/down): %d/%d KB/s, peak: %d/%d KB/s",
|
||||
user->hub->users->count,
|
||||
user->hub->users->count_peak,
|
||||
(int) user->hub->stats.net_tx / 1024,
|
||||
(int) user->hub->stats.net_rx / 1024,
|
||||
(int) user->hub->stats.net_tx_peak / 1024,
|
||||
(int) user->hub->stats.net_rx_peak / 1024);
|
||||
|
||||
char* buffer = adc_msg_escape(temp);
|
||||
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||
adc_msg_add_argument(command, buffer);
|
||||
route_to_user(user, command);
|
||||
adc_msg_free(command);
|
||||
hub_free(buffer);
|
||||
return 0;
|
||||
|
||||
send_message(user, temp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int command_help(struct user* user, const char* message)
|
||||
{
|
||||
struct adc_message* command;
|
||||
char* buffer = adc_msg_escape("\n"
|
||||
"*** Available commands:\n"
|
||||
"!help - Show this help message\n"
|
||||
"!stats - Show hub stats (super)\n"
|
||||
"!version - Show this help message\n"
|
||||
"!uptime - Display hub uptime\n"
|
||||
"!kick <user> - Kick user (operator)\n"
|
||||
);
|
||||
|
||||
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||
adc_msg_add_argument(command, buffer);
|
||||
route_to_user(user, command);
|
||||
adc_msg_free(command);
|
||||
hub_free(buffer);
|
||||
#define MAX_HELP_MSG 1024
|
||||
size_t n;
|
||||
char msg[MAX_HELP_MSG];
|
||||
msg[0] = 0;
|
||||
strcat(msg, "\n*** Available commands:\n");
|
||||
|
||||
for (n = 0; command_handlers[n].prefix; n++)
|
||||
{
|
||||
if (command_handlers[n].cred <= user->credentials)
|
||||
{
|
||||
strcat(msg, command_handlers[n].prefix);
|
||||
strcat(msg, " - ");
|
||||
strcat(msg, command_handlers[n].description);
|
||||
strcat(msg, "\n");
|
||||
}
|
||||
}
|
||||
send_message(user, msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int command_uptime(struct user* user, const char* message)
|
||||
{
|
||||
struct adc_message* command;
|
||||
char tmp[128];
|
||||
size_t d;
|
||||
size_t h;
|
||||
size_t m;
|
||||
size_t D = (size_t) difftime(time(0), user->hub->tm_started);
|
||||
char tmp[128];
|
||||
size_t d;
|
||||
size_t h;
|
||||
size_t m;
|
||||
size_t D = (size_t) difftime(time(0), user->hub->tm_started);
|
||||
|
||||
d = D / (24 * 3600);
|
||||
D = D % (24 * 3600);
|
||||
h = D / 3600;
|
||||
D = D % 3600;
|
||||
m = D / 60;
|
||||
d = D / (24 * 3600);
|
||||
D = D % (24 * 3600);
|
||||
h = D / 3600;
|
||||
D = D % 3600;
|
||||
m = D / 60;
|
||||
|
||||
tmp[0] = 0;
|
||||
strcat(tmp, "*** Uptime: ");
|
||||
|
||||
if (d)
|
||||
{
|
||||
strcat(tmp, uhub_itoa((int) d));
|
||||
strcat(tmp, " day");
|
||||
if (d != 1) strcat(tmp, "s");
|
||||
strcat(tmp, ", ");
|
||||
}
|
||||
tmp[0] = 0;
|
||||
strcat(tmp, "*** Uptime: ");
|
||||
|
||||
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));
|
||||
if (d)
|
||||
{
|
||||
strcat(tmp, uhub_itoa((int) d));
|
||||
strcat(tmp, " day");
|
||||
if (d != 1) strcat(tmp, "s");
|
||||
strcat(tmp, ", ");
|
||||
}
|
||||
|
||||
char* buffer = adc_msg_escape(tmp);
|
||||
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||
adc_msg_add_argument(command, buffer);
|
||||
route_to_user(user, command);
|
||||
adc_msg_free(command);
|
||||
hub_free(buffer);
|
||||
return 0;
|
||||
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));
|
||||
|
||||
send_message(user, tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int command_kick(struct user* user, const char* message)
|
||||
{
|
||||
struct adc_message* command;
|
||||
|
||||
if (user->credentials < cred_operator)
|
||||
return command_access_denied(user);
|
||||
|
||||
char* buffer = adc_msg_escape("*** Kick not implemented!");
|
||||
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||
adc_msg_add_argument(command, buffer);
|
||||
route_to_user(user, command);
|
||||
adc_msg_free(command);
|
||||
hub_free(buffer);
|
||||
return 0;
|
||||
send_message(user, "*** Kick not implemented!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int command_reload(struct user* user, const char* message)
|
||||
{
|
||||
send_message(user, "*** Reloading configuration");
|
||||
user->hub->status = hub_status_restart;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int command_shutdown(struct user* user, const char* message)
|
||||
{
|
||||
send_message(user, "*** Hub shuting down...");
|
||||
user->hub->status = hub_status_shutdown;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int command_version(struct user* user, const char* message)
|
||||
{
|
||||
struct adc_message* command;
|
||||
char* buffer = adc_msg_escape("*** Powered by " PRODUCT "/" VERSION);
|
||||
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||
adc_msg_add_argument(command, buffer);
|
||||
route_to_user(user, command);
|
||||
adc_msg_free(command);
|
||||
hub_free(buffer);
|
||||
send_message(user, "*** Powered by " PRODUCT "/" VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int command_myip(struct user* user, const char* message)
|
||||
{
|
||||
struct adc_message* command;
|
||||
char tmp[128];
|
||||
char* buffer;
|
||||
|
||||
tmp[0] = 0;
|
||||
strcat(tmp, "*** Your IP: ");
|
||||
strcat(tmp, ip_convert_to_string(&user->ipaddr));
|
||||
|
||||
buffer = adc_msg_escape(tmp);
|
||||
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||
adc_msg_add_argument(command, buffer);
|
||||
route_to_user(user, command);
|
||||
adc_msg_free(command);
|
||||
hub_free(buffer);
|
||||
snprintf(tmp, 128, "*** Your IP: %s", ip_convert_to_string(&user->ipaddr));
|
||||
send_message(user, tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int command_dipatcher(struct user* user, const char* message)
|
||||
{
|
||||
if (!strncmp(message, "!stats", 6)) command_stats(user, message);
|
||||
else if (!strncmp(message, "!help", 5)) command_help(user, message);
|
||||
else if (!strncmp(message, "!kick", 5)) command_kick(user, message);
|
||||
else if (!strncmp(message, "!version", 8)) command_version(user, message);
|
||||
else if (!strncmp(message, "!uptime", 7)) command_uptime(user, message);
|
||||
else if (!strncmp(message, "+myip", 5)) command_myip(user, message);
|
||||
else
|
||||
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(user, message);
|
||||
}
|
||||
else
|
||||
{
|
||||
return command_access_denied(user, &command_handlers[n].prefix[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct commands_handler command_handlers[] = {
|
||||
{ "!help", 5, cred_guest, command_help, "Show this help message." },
|
||||
{ "!stats", 6, cred_super, command_stats, "Show hub statistics." },
|
||||
{ "!version", 8, cred_guest, command_version, "Show hub version info." },
|
||||
{ "!uptime", 7, cred_guest, command_uptime, "Display hub uptime info." },
|
||||
{ "!kick", 5, cred_operator, command_kick, "Kick a user" },
|
||||
{ "!reload", 7, cred_admin, command_reload, "Reload configuration files." },
|
||||
{ "!shutdown", 9, cred_admin, command_shutdown, "Shutdown hub." },
|
||||
{ "+myip", 5, cred_guest, command_myip, "Show your own IP." },
|
||||
{ 0, 0, cred_none, command_help, "{ Last dummy option }" }
|
||||
};
|
||||
|
||||
|
||||
46
src/hub.c
46
src/hub.c
@@ -479,7 +479,11 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
||||
net_address_to_string(AF_INET6, &((struct sockaddr_in6*) &addr)->sin6_addr, address_buf, INET6_ADDRSTRLEN);
|
||||
}
|
||||
|
||||
#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.");
|
||||
@@ -487,7 +491,7 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
||||
return 0;
|
||||
}
|
||||
|
||||
hub_log(log_info, "Starting server, listening on %s:%d...", address_buf, config->server_port);
|
||||
hub_log(log_info, "Starting " PRODUCT "/" VERSION ", listening on %s:%d...", address_buf, config->server_port);
|
||||
|
||||
server_tcp = net_socket_create(af, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (server_tcp == -1)
|
||||
@@ -894,6 +898,46 @@ const char* hub_get_status_message(struct hub_info* hub, enum status_message msg
|
||||
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;
|
||||
|
||||
@@ -238,6 +238,8 @@ extern void hub_free_variables(struct hub_info* hub);
|
||||
* Returns a string for the given status_message (See enum status_message).
|
||||
*/
|
||||
extern const char* hub_get_status_message(struct hub_info* hub, enum status_message msg);
|
||||
extern const char* hub_get_status_message_log(struct hub_info* hub, enum status_message msg);
|
||||
|
||||
|
||||
/**
|
||||
* Sends a status_message to a user.
|
||||
|
||||
@@ -19,12 +19,36 @@
|
||||
|
||||
#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 user* u)
|
||||
{
|
||||
/* Logging - FIXME: Move this to a plugin */
|
||||
const char* addr = ip_convert_to_string(&u->ipaddr);
|
||||
const char* credentials_string[] = { "!none!", "link", "guest", "user", "operator", "super", "admin" };
|
||||
struct timeval timeout = { TIMEOUT_IDLE, 0 };
|
||||
|
||||
/* Send user list of all existing users */
|
||||
@@ -36,7 +60,7 @@ void on_login_success(struct user* u)
|
||||
user_manager_add(u);
|
||||
|
||||
/* Print log message */
|
||||
hub_log(log_user, "Login OK %s/%s \"%s\" [%s] (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, u->id.nick, addr, credentials_string[u->credentials], u->user_agent);
|
||||
log_user_login(u);
|
||||
|
||||
/* Announce new user to all connected users */
|
||||
if (user_is_logged_in(u))
|
||||
@@ -51,36 +75,29 @@ void on_login_success(struct user* u)
|
||||
event_add(u->ev_read, &timeout);
|
||||
}
|
||||
|
||||
|
||||
void on_login_failure(struct user* u, enum status_message msg)
|
||||
{
|
||||
const char* addr = ip_convert_to_string(&u->ipaddr);
|
||||
const char* message = hub_get_status_message(u->hub, msg);
|
||||
hub_log(log_user, "Login FAIL %s/%s \"%s\" [%s] (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, u->id.nick, addr, message, u->user_agent);
|
||||
|
||||
log_user_login_error(u, msg);
|
||||
hub_send_status(u, msg, status_level_fatal);
|
||||
user_disconnect(u, quit_logon_error);
|
||||
}
|
||||
|
||||
|
||||
void on_nick_change(struct user* u, const char* nick)
|
||||
{
|
||||
if (user_is_logged_in(u))
|
||||
{
|
||||
hub_log(log_user, "Nick change %s/%s \"%s\" -> \"%s\"", sid_to_string(u->id.sid), u->id.cid, u->id.nick, nick);
|
||||
log_user_nick_change(u, nick);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void on_logout_user(struct user* user)
|
||||
{
|
||||
const char* reason = "";
|
||||
const char* addr;
|
||||
|
||||
/* These are used for logging purposes */
|
||||
switch (user->quit_reason)
|
||||
{
|
||||
case quit_disconnected: reason = "disconnected"; break;
|
||||
case quit_disconnected: reason = "disconnected"; break;
|
||||
case quit_kicked: reason = "kicked"; break;
|
||||
case quit_banned: reason = "banned"; break;
|
||||
case quit_timeout: reason = "timeout"; break;
|
||||
@@ -90,6 +107,7 @@ void on_logout_user(struct user* user)
|
||||
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 (user->hub->status == hub_status_shutdown)
|
||||
reason = "hub shutdown";
|
||||
@@ -98,10 +116,7 @@ void on_logout_user(struct user* user)
|
||||
break;
|
||||
}
|
||||
|
||||
addr = ip_convert_to_string(&user->ipaddr);
|
||||
hub_log(log_user, "Logout %s/%s \"%s\" [%s] (%s)", sid_to_string(user->id.sid), user->id.cid, user->id.nick, addr, reason);
|
||||
|
||||
|
||||
log_user_logout(user, reason);
|
||||
user->quit_reason = 0;
|
||||
}
|
||||
|
||||
|
||||
15
src/inf.c
15
src/inf.c
@@ -332,7 +332,7 @@ static int check_logged_in(struct user* user, struct adc_message* cmd)
|
||||
if (lookup1 == lookup2)
|
||||
{
|
||||
hub_log(log_debug, "check_logged_in: exact same user is logged in: %s", user->id.nick);
|
||||
user_disconnect(lookup1, quit_timeout);
|
||||
user_disconnect(lookup1, quit_ghost_timeout);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
@@ -645,6 +645,7 @@ void update_user_info(struct user* u, struct adc_message* cmd)
|
||||
argument = adc_msg_get_argument(cmd, n++);
|
||||
}
|
||||
user_set_info(u, cmd_new);
|
||||
adc_msg_free(cmd_new);
|
||||
}
|
||||
|
||||
|
||||
@@ -766,7 +767,7 @@ int hub_handle_info_login(struct user* user, struct adc_message* cmd)
|
||||
*/
|
||||
int hub_handle_info(struct user* user, const struct adc_message* cmd_unmodified)
|
||||
{
|
||||
struct adc_message* cmd = adc_msg_copy(cmd_unmodified); /* FIXME: Have a small memory leak here! */
|
||||
struct adc_message* cmd = adc_msg_copy(cmd_unmodified);
|
||||
if (!cmd) return -1; /* OOM */
|
||||
|
||||
cmd->priority = 1;
|
||||
@@ -778,6 +779,16 @@ int hub_handle_info(struct user* user, const struct adc_message* cmd_unmodified)
|
||||
*/
|
||||
if (user_is_connecting(user))
|
||||
{
|
||||
/*
|
||||
* Don't allow the user to send multiple INF messages in this stage!
|
||||
* Since that can have serious side-effects.
|
||||
*/
|
||||
if (user->info)
|
||||
{
|
||||
adc_msg_free(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = hub_handle_info_login(user, cmd);
|
||||
if (ret < 0)
|
||||
{
|
||||
|
||||
@@ -177,8 +177,8 @@ void hub_log(int log_verbosity, const char *format, ...)
|
||||
if (log_verbosity < verbosity)
|
||||
{
|
||||
t = time(NULL);
|
||||
tmp = gmtime(&t);
|
||||
strftime(timestamp, 32, "%a, %d %b %Y %H:%M:%S +0000", tmp);
|
||||
tmp = localtime(&t);
|
||||
strftime(timestamp, 32, "%Y-%m-%d %H:%M:%S", tmp);
|
||||
va_start(args, format);
|
||||
vsnprintf(logmsg, 1024, format, args);
|
||||
va_end(args);
|
||||
|
||||
29
src/main.c
29
src/main.c
@@ -37,47 +37,29 @@ void hub_handle_signal(int fd, short events, void* arg)
|
||||
{
|
||||
struct hub_info* hub = (struct hub_info*) arg;
|
||||
int signal = fd;
|
||||
struct timeval now = {0, 0};
|
||||
|
||||
switch (signal)
|
||||
{
|
||||
case SIGINT:
|
||||
hub_log(log_info, "Interrupted. Shutting down...");
|
||||
hub->status = hub_status_shutdown;
|
||||
event_loopexit(&now);
|
||||
break;
|
||||
|
||||
case SIGTERM:
|
||||
hub_log(log_info, "Terminated. Shutting down...");
|
||||
hub->status = hub_status_shutdown;
|
||||
event_loopexit(&now);
|
||||
break;
|
||||
|
||||
case SIGPIPE:
|
||||
hub_log(log_trace, "hub_handle_signal(): caught SIGPIPE (ignoring)");
|
||||
break;
|
||||
|
||||
case SIGHUP:
|
||||
hub_log(log_info, "Caught hangup signal. Reloading configuration files...");
|
||||
hub->status = hub_status_restart;
|
||||
event_loopexit(&now);
|
||||
break;
|
||||
|
||||
case SIGUSR1:
|
||||
hub_log(log_trace, "hub_handle_signal(): caught SIGUSR1 -- FIXME");
|
||||
break;
|
||||
|
||||
case SIGUSR2:
|
||||
hub_log(log_trace, "hub_handle_signal(): caught SIGUSR2");
|
||||
{
|
||||
user_manager_print_stats(hub);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
hub_log(log_trace, "hub_handle_signal(): caught unknown signal: %d", signal);
|
||||
hub->status = hub_status_shutdown;
|
||||
event_loopexit(&now);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -89,8 +71,6 @@ static int signals[] =
|
||||
SIGTERM, /* Terminate the application */
|
||||
SIGPIPE, /* prevent sigpipe from kills the application */
|
||||
SIGHUP, /* reload configuration */
|
||||
SIGUSR1, /* dump statistics */
|
||||
SIGUSR2, /* (unused) */
|
||||
0
|
||||
};
|
||||
|
||||
@@ -131,6 +111,12 @@ int main_loop()
|
||||
|
||||
do
|
||||
{
|
||||
if (hub)
|
||||
{
|
||||
hub_log(log_info, "Reloading configuration files...");
|
||||
hub_log(log_debug, "Hub status: %d", (int) hub->status);
|
||||
}
|
||||
|
||||
if (read_config(arg_config, &configuration, !arg_have_config) == -1)
|
||||
return -1;
|
||||
|
||||
@@ -188,6 +174,9 @@ int check_configuration(int dump)
|
||||
puts("");
|
||||
}
|
||||
|
||||
if (dump)
|
||||
return 0;
|
||||
|
||||
if (ret == -1)
|
||||
{
|
||||
fprintf(stderr, "ERROR\n");
|
||||
|
||||
@@ -263,6 +263,13 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
|
||||
if (command == NULL)
|
||||
return NULL; /* OOM */
|
||||
|
||||
if (!is_printable_utf8(line, length))
|
||||
{
|
||||
hub_log(log_debug, "Dropped message with non-printable UTF-8 characters.");
|
||||
hub_free(command);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (line[length-1] != '\n')
|
||||
{
|
||||
|
||||
35
src/misc.c
35
src/misc.c
@@ -31,6 +31,16 @@ int is_white_space(char c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_printable(unsigned char c)
|
||||
{
|
||||
if (c >= 32)
|
||||
return 1;
|
||||
|
||||
if (c == '\t' || c == '\r' || c == '\n')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char* strip_white_space(char* string)
|
||||
{
|
||||
@@ -48,17 +58,15 @@ char* strip_white_space(char* string)
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
int is_valid_utf8(const char* string)
|
||||
static int is_valid_utf8_str(const char* string, size_t length)
|
||||
{
|
||||
int expect = 0;
|
||||
char div = 0;
|
||||
int pos = 0;
|
||||
int length = strlen(string);
|
||||
size_t pos = 0;
|
||||
|
||||
if (length == 0) return 1;
|
||||
|
||||
for (pos = 0; pos < strlen(string); pos++)
|
||||
for (pos = 0; pos < length; pos++)
|
||||
{
|
||||
if (expect)
|
||||
{
|
||||
@@ -74,13 +82,28 @@ int is_valid_utf8(const char* string)
|
||||
if (string[pos] & div) expect++;
|
||||
else break;
|
||||
}
|
||||
if ((string[pos] & div) || (pos+expect >= strlen(string))) return 0;
|
||||
if ((string[pos] & div) || (pos+expect >= length)) return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int is_valid_utf8(const char* string)
|
||||
{
|
||||
return is_valid_utf8_str(string, strlen(string));
|
||||
}
|
||||
|
||||
int is_printable_utf8(const char* string, size_t length)
|
||||
{
|
||||
size_t pos = 0;
|
||||
for (pos = 0; pos < length; pos++)
|
||||
{
|
||||
if (!is_printable(string[pos]))
|
||||
return 0;
|
||||
}
|
||||
return is_valid_utf8_str(string, length);
|
||||
}
|
||||
|
||||
int is_valid_base32_char(char c)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,7 @@ extern int is_num(char c);
|
||||
extern int is_space(char c);
|
||||
extern int is_white_space(char c);
|
||||
extern int is_valid_utf8(const char* string);
|
||||
extern int is_printable_utf8(const char* string, size_t length);
|
||||
extern int is_valid_base32_char(char c);
|
||||
extern void base32_encode(const unsigned char* buffer, size_t len, char* result);
|
||||
extern void base32_decode(const char* src, unsigned char* dst, size_t len);
|
||||
|
||||
@@ -25,10 +25,9 @@ void net_on_read(int fd, short ev, void *arg)
|
||||
static char buf[MAX_RECV_BUF];
|
||||
struct user* user = (struct user*) arg;
|
||||
char* pos;
|
||||
char* start;
|
||||
ssize_t offset;
|
||||
size_t offset;
|
||||
size_t buflen;
|
||||
ssize_t size;
|
||||
ssize_t buflen;
|
||||
int more = 1;
|
||||
int flag_close = 0;
|
||||
|
||||
@@ -55,11 +54,7 @@ void net_on_read(int fd, short ev, void *arg)
|
||||
memcpy(buf, user->recv_buf, user->recv_buf_offset);
|
||||
offset = user->recv_buf_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
|
||||
size = net_recv(fd, &buf[offset], MAX_RECV_BUF - offset, 0);
|
||||
if (size == -1)
|
||||
{
|
||||
@@ -75,40 +70,63 @@ void net_on_read(int fd, short ev, void *arg)
|
||||
else
|
||||
{
|
||||
buflen = offset + size;
|
||||
start = buf;
|
||||
while ((pos = strchr(start, '\n')))
|
||||
ssize_t handled = 0;
|
||||
|
||||
while ((pos = memchr(&buf[handled], '\n', (buflen - handled))))
|
||||
{
|
||||
pos[0] = '\0';
|
||||
if (*start && strlen(start) < user->hub->config->max_recv_buffer)
|
||||
{
|
||||
if (hub_handle_message(user, start, &pos[0]-&start[0]) == -1)
|
||||
{
|
||||
flag_close = quit_protocol_error;
|
||||
more = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
start = &pos[1];
|
||||
}
|
||||
|
||||
if (!more) break;
|
||||
|
||||
if (&buf[offset + size] > &start[0])
|
||||
{
|
||||
if (!user->recv_buf)
|
||||
{
|
||||
user->recv_buf = hub_malloc(user->hub->config->max_recv_buffer);
|
||||
}
|
||||
size_t msglen = &pos[0] - &buf[handled];
|
||||
|
||||
if (!user->recv_buf)
|
||||
if (user_flag_get(user, flag_maxbuf))
|
||||
{
|
||||
flag_close = quit_memory_error;
|
||||
break;
|
||||
user_flag_unset(user, flag_maxbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(user->recv_buf, start, &buf[offset + size] - &start[0]);
|
||||
user->recv_buf_offset = &buf[offset + size] - &start[0];
|
||||
if (msglen < user->hub->config->max_recv_buffer)
|
||||
{
|
||||
if (hub_handle_message(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
|
||||
@@ -242,13 +260,13 @@ void net_on_accept(int server_fd, short ev, void *arg)
|
||||
{
|
||||
struct hub_info* hub = (struct hub_info*) arg;
|
||||
struct user* user = 0;
|
||||
int accept_more = 1;
|
||||
struct ip_addr_encap ipaddr;
|
||||
const char* addr;
|
||||
struct timeval timeout = { TIMEOUT_CONNECTED, 0 };
|
||||
|
||||
while (accept_more)
|
||||
for (;;)
|
||||
{
|
||||
int fd = net_accept(server_fd);
|
||||
int fd = net_accept(server_fd, &ipaddr);
|
||||
if (fd == -1)
|
||||
{
|
||||
if (net_error() == EWOULDBLOCK)
|
||||
@@ -262,7 +280,7 @@ void net_on_accept(int server_fd, short ev, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
addr = net_get_peer_address(fd);
|
||||
addr = ip_convert_to_string(&ipaddr);
|
||||
|
||||
/* FIXME: Should have a plugin log this */
|
||||
hub_log(log_trace, "Got connection from %s", addr);
|
||||
@@ -284,7 +302,7 @@ void net_on_accept(int server_fd, short ev, void *arg)
|
||||
}
|
||||
|
||||
/* Store IP address in user object */
|
||||
ip_convert_to_binary(addr, &user->ipaddr);
|
||||
memcpy(&user->ipaddr, &ipaddr, sizeof(ipaddr));
|
||||
|
||||
net_set_nonblocking(fd, 1);
|
||||
net_set_nosigpipe(fd, 1);
|
||||
@@ -294,7 +312,6 @@ void net_on_accept(int server_fd, short ev, void *arg)
|
||||
event_base_set(hub->evbase, user->ev_read);
|
||||
event_base_set(hub->evbase, user->ev_write);
|
||||
event_add(user->ev_read, &timeout);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -236,13 +236,19 @@ int net_close(int fd)
|
||||
}
|
||||
|
||||
|
||||
int net_accept(int fd)
|
||||
int net_accept(int fd, struct ip_addr_encap* ipaddr)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
struct sockaddr_in* addr4;
|
||||
struct sockaddr_in6* addr6;
|
||||
socklen_t addr_size;
|
||||
int ret = 0;
|
||||
addr_size = sizeof(struct sockaddr_storage);
|
||||
|
||||
memset(&addr, 0, addr_size);
|
||||
addr4 = (struct sockaddr_in*) &addr;
|
||||
addr6 = (struct sockaddr_in6*) &addr;
|
||||
|
||||
ret = accept(fd, (struct sockaddr*) &addr, &addr_size);
|
||||
|
||||
if (ret == -1)
|
||||
@@ -270,6 +276,20 @@ int net_accept(int fd)
|
||||
else
|
||||
{
|
||||
net_stats_add_accept();
|
||||
|
||||
if (ipaddr)
|
||||
{
|
||||
memset(ipaddr, 0, sizeof(struct ip_addr_encap));
|
||||
ipaddr->af = addr4->sin_family;
|
||||
if (ipaddr->af == AF_INET6)
|
||||
{
|
||||
memcpy(&ipaddr->internal_ip_data.in6, &addr6->sin6_addr, sizeof(struct in6_addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&ipaddr->internal_ip_data.in, &addr4->sin_addr, sizeof(struct in_addr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -465,11 +485,9 @@ const char* net_get_peer_address(int fd)
|
||||
name4 = (struct sockaddr_in*) &storage;
|
||||
name = (struct sockaddr*) &storage;
|
||||
|
||||
|
||||
int af = net_is_ipv6_supported() ? AF_INET6 : AF_INET;
|
||||
|
||||
if (getpeername(fd, (struct sockaddr*) name, &namelen) != -1)
|
||||
{
|
||||
int af = name4->sin_family;
|
||||
if (af == AF_INET6)
|
||||
{
|
||||
net_address_to_string(af, (void*) &name6->sin6_addr, address, INET6_ADDRSTRLEN);
|
||||
|
||||
@@ -83,8 +83,11 @@ extern int net_close(int fd);
|
||||
|
||||
/**
|
||||
* A wrapper for the accept() function call.
|
||||
* @param fd socket descriptor
|
||||
* @param ipaddr (in/out) if non-NULL the ip address of the
|
||||
* accepted peer is filled in.
|
||||
*/
|
||||
extern int net_accept(int fd);
|
||||
extern int net_accept(int fd, struct ip_addr_encap* ipaddr);
|
||||
|
||||
/**
|
||||
* A wrapper for the connect() call.
|
||||
|
||||
16
src/user.h
16
src/user.h
@@ -35,7 +35,7 @@ enum user_state
|
||||
};
|
||||
|
||||
|
||||
enum user_flags
|
||||
enum user_flags
|
||||
{
|
||||
feature_base = 0x00000001, /** BASE: Basic configuration (required by all clients) */
|
||||
feature_auto = 0x00000002, /** AUT0: Automatic nat detection traversal */
|
||||
@@ -47,11 +47,12 @@ enum user_flags
|
||||
feature_ping = 0x00000080, /** PING: Hub pinger information extension */
|
||||
feature_link = 0x00000100, /** LINK: Hub link (not supported) */
|
||||
flag_ignore = 0x01000000, /** Ignore further reads */
|
||||
flag_choke = 0x02000000, /** Choked: Cannot send, waiting for write event */
|
||||
flag_want_read = 0x04000000, /** Need to read (SSL) */
|
||||
flag_want_write = 0x08000000, /** Need to write (SSL) */
|
||||
flag_user_list = 0x10000000, /** Send queue bypass (when receiving the send queue) */
|
||||
flag_nat = 0x20000000, /** nat override enabled */
|
||||
flag_maxbuf = 0x02000000, /** Hit max buf read, ignore msg */
|
||||
flag_choke = 0x04000000, /** Choked: Cannot send, waiting for write event */
|
||||
flag_want_read = 0x08000000, /** Need to read (SSL) */
|
||||
flag_want_write = 0x10000000, /** Need to write (SSL) */
|
||||
flag_user_list = 0x20000000, /** Send queue bypass (when receiving the send queue) */
|
||||
flag_nat = 0x40000000, /** nat override enabled */
|
||||
};
|
||||
|
||||
|
||||
@@ -68,12 +69,13 @@ enum user_quit_reason
|
||||
quit_protocol_error = 8, /** Fatal protocol error */
|
||||
quit_logon_error = 9, /** Unable to login (wrong password, CID/PID, etc) */
|
||||
quit_hub_disabled = 10, /** Hub is disabled. No new connections allowed */
|
||||
quit_ghost_timeout = 11, /** The user is a ghost, and trying to login from another connection */
|
||||
};
|
||||
|
||||
|
||||
struct user_info
|
||||
{
|
||||
sid_t sid; /** session ID */
|
||||
sid_t sid; /** session ID */
|
||||
char cid[MAX_CID_LEN+1]; /** global client ID */
|
||||
char nick[MAX_NICK_LEN+1]; /** User's nick name */
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user