Merged changes from github.

Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
This commit is contained in:
Jan Vidar Krey 2009-03-13 16:54:39 +01:00
commit f6af8cf389
20 changed files with 195 additions and 121 deletions

View File

@ -1,3 +1,12 @@
0.2.6:
- Better "!uptime" command formatting.
- Better "!stats"; can display peak and current bandwidth usage.
- Added "+myip" command.
- Ensure super users and hub owners also have the operator flag set.
- Bug #1: Better dynamic send queue handling for large hubs at the cost of more memory use.
- Bug #5: Always provide IP-address to all users, not just for active clients.
0.2.5-3487:
- Fixed out of memory situations, used when uhub operates on a limited heap.
- Code cleanups, reduced heap memory footprint.

View File

@ -134,8 +134,8 @@ typedef uint32_t fourcc_t;
#define ADC_CLIENT_TYPE_BOT "1"
#define ADC_CLIENT_TYPE_REGISTERED_USER "2"
#define ADC_CLIENT_TYPE_OPERATOR "4"
#define ADC_CLIENT_TYPE_SUPER_USER "8"
#define ADC_CLIENT_TYPE_ADMIN "16" /* hub owner */
#define ADC_CLIENT_TYPE_SUPER_USER "12" /* 8 + 4 */
#define ADC_CLIENT_TYPE_ADMIN "20" /* 16 + 4 = hub owner */
#define ADC_CLIENT_TYPE_HUB "32" /* the hub itself */

View File

@ -53,7 +53,7 @@ static int check_cmd_bool(const char* cmd, struct linked_list* list, char* line,
data++;
data = strip_white_space(data);
if (!strlen(data))
if (!*data)
{
hub_log(log_fatal, "ACL parse error on line %d", line_count);
return -1;
@ -80,7 +80,7 @@ static int check_cmd_user(const char* cmd, int status, struct linked_list* list,
data++;
data = strip_white_space(data);
if (!strlen(data))
if (!*data)
{
hub_log(log_fatal, "ACL parse error on line %d", line_count);
return -1;
@ -192,7 +192,7 @@ static int check_cmd_addr(const char* cmd, struct linked_list* list, char* line,
data1++;
data1 = strip_white_space(data1);
if (!strlen(data1))
if (!*data1)
{
hub_log(log_fatal, "ACL parse error on line %d", line_count);
return -1;
@ -266,7 +266,7 @@ static int acl_parse_line(char* line, int line_count, void* ptr_data)
pos[0] = 0;
}
if (strlen(line) == 0)
if (!*line)
return 0;
#ifdef ACL_DEBUG
@ -274,7 +274,7 @@ static int acl_parse_line(char* line, int line_count, void* ptr_data)
#endif
line = strip_white_space(line);
if (!strlen(line))
if (!*line)
{
hub_log(log_fatal, "ACL parse error on line %d", line_count);
return -1;
@ -328,7 +328,7 @@ int acl_initialize(struct hub_config* config, struct acl_handle* handle)
if (config)
{
if (strlen(config->file_acl) == 0) return 0;
if (!*config->file_acl) return 0;
ret = file_read_lines(config->file_acl, handle, &acl_parse_line);
if (ret == -1)

View File

@ -39,8 +39,16 @@ static int command_stats(struct user* user, const char* message)
if (user->credentials < cred_super)
return command_access_denied(user);
char temp[64];
snprintf(temp, 64, "*** Stats: %u users, peak %u", (unsigned int) user->hub->users->count, (unsigned int) user->hub->users->count_peak);
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);
@ -54,7 +62,7 @@ static int command_stats(struct user* user, const char* message)
static int command_help(struct user* user, const char* message)
{
struct adc_message* command;
char* buffer = adc_msg_escape(
char* buffer = adc_msg_escape("\n"
"*** Available commands:\n"
"!help - Show this help message\n"
"!stats - Show hub stats (super)\n"
@ -74,9 +82,36 @@ static int command_help(struct user* user, const char* message)
static int command_uptime(struct user* user, const char* message)
{
struct adc_message* command;
char temp[64];
snprintf(temp, 64, "*** Uptime: %s seconds", uhub_itoa((int) difftime(time(0), user->hub->tm_started)));
char* buffer = adc_msg_escape(temp);
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;
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, ", ");
}
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));
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);
@ -113,6 +148,26 @@ static int command_version(struct user* user, const char* message)
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);
return 0;
}
int command_dipatcher(struct user* user, const char* message)
{
if (!strncmp(message, "!stats", 6)) command_stats(user, message);
@ -120,6 +175,7 @@ int command_dipatcher(struct user* user, const char* 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
return 1;
return 0;

View File

@ -64,7 +64,7 @@
int val; \
errno = 0; \
val = strtol(data, &endptr, 10); \
if (((errno == ERANGE && (val == INT_MAX || val == INT_MIN)) || (errno != 0 && val == 0)) || endptr == data /*|| endptr != &data[strlen(data)-1]*/) { \
if (((errno == ERANGE && (val == INT_MAX || val == INT_MIN)) || (errno != 0 && val == 0)) || endptr == data) { \
hub_log(log_fatal, "Configuration error on line %d: '%s' must be a number", line_count, key); \
return -1; \
} \
@ -458,7 +458,7 @@ static int config_parse_line(char* line, int line_count, void* ptr_data)
pos[0] = 0;
}
if (strlen(line) == 0) return 0;
if (!*line) return 0;
#ifdef CONFIG_DUMP
hub_log(log_trace, "config_parse_line(): '%s'", line);
@ -479,7 +479,7 @@ static int config_parse_line(char* line, int line_count, void* ptr_data)
key = strip_white_space(key);
data = strip_white_space(data);
if (!strlen(key) || !strlen(data))
if (!*key || !*data)
{
hub_log(log_fatal, "Configuration parse error on line %d", line_count);
return -1;

View File

@ -35,8 +35,8 @@ struct hub_config
char* hub_name; /**<<< "Name of hub (default: 'My uhub hub')" */
char* hub_description; /**<<< "Name of hub (default: 'no description')" */
int max_recv_buffer; /**<<< "Max read buffer before parse, per user (default: 4096)" */
int max_send_buffer; /**<<< "Max send buffer before disconnect, per user (default: 16384)" */
int max_send_buffer_soft; /**<<< "Max send buffer before message drops, per user (default: 8192)" */
int max_send_buffer; /**<<< "Max send buffer before disconnect, per user (default: 128K)" */
int max_send_buffer_soft; /**<<< "Max send buffer before message drops, per user (default: 96K)" */
int low_bandwidth_mode; /**<<< "If this is enabled, the hub will strip off elements from each user's info message to reduce bandwidth usage" */
/* Limits enforced on users */

View File

@ -189,7 +189,7 @@ int hub_handle_chat_message(struct user* u, struct adc_message* cmd)
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] == '!')
if (message[0] == '!' || message[0] == '+')
{
relay = command_dipatcher(u, message);
}

View File

@ -66,6 +66,19 @@ enum hub_state
hub_status_disabled = 5, /**<<<"Hub is disabled (Running, but not accepting users) */
};
/**
* Always updated each minute.
*/
struct hub_stats
{
size_t net_tx;
size_t net_rx;
size_t net_tx_peak;
size_t net_rx_peak;
size_t net_tx_total;
size_t net_rx_total;
};
struct hub_info
{
int fd_tcp;
@ -77,6 +90,7 @@ struct hub_info
#ifdef ADC_UDP_OPERATION
struct event ev_datagram;
#endif
struct hub_stats stats;
struct event_queue* queue;
struct hub_config* config;
struct user_manager* users;

View File

@ -58,7 +58,7 @@ static int set_feature_cast_supports(struct user* u, struct adc_message* cmd)
it = &it[5];
}
if (strlen(it) > 0)
if (*it)
{
user_set_feature_cast_support(u, it);
}
@ -188,65 +188,37 @@ static int check_required_login_flags(struct user* user, struct adc_message* cmd
*/
int check_network(struct user* user, struct adc_message* cmd)
{
int want_ipv4 = 0;
int want_ipv6 = 0;
int nat_override = 0;
const char* address = 0;
const char* address = ip_convert_to_string(&user->ipaddr);
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR))
{
want_ipv6 = 1;
}
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR))
{
want_ipv4 = 1;
}
if (!want_ipv4 && !want_ipv6)
return 0;
/* Add correct/verified IP addresses instead (if requested/stripped) */
address = (char*) net_get_peer_address(user->sd);
if (address)
{
if (want_ipv4 && strchr(address, '.'))
{
want_ipv6 = 0;
}
else if (want_ipv6)
{
want_ipv4 = 0;
}
/* check if user can do nat override */
if (want_ipv4 && acl_is_ip_nat_override(user->hub->acl, address))
/* Check for NAT override address */
if (acl_is_ip_nat_override(user->hub->acl, address))
{
char* client_given_ip = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
if (strcmp(client_given_ip, "0.0.0.0") != 0)
{
user_set_nat_override(user);
nat_override = 1;
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT);
hub_free(client_given_ip);
return 0;
}
hub_free(client_given_ip);
}
}
if (!nat_override)
if (strchr(address, '.'))
{
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR, address);
}
else if (strchr(address, ':'))
{
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
if (!want_ipv4)
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_UDP_PORT);
else
adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR, address);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
if (!want_ipv6)
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT);
else
adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR, address);
}
return 0;
}
@ -359,7 +331,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);
hub_log(log_error, "check_logged_in: exact same user is logged in: %s", user->id.nick);
user_disconnect(lookup1, quit_timeout);
return 0;
}

View File

@ -90,7 +90,7 @@ int ip_convert_to_binary(const char* taddr, struct ip_addr_encap* raw)
}
char* ip_convert_to_string(struct ip_addr_encap* raw)
const char* ip_convert_to_string(struct ip_addr_encap* raw)
{
static char address[INET6_ADDRSTRLEN+1];
memset(address, 0, INET6_ADDRSTRLEN);

View File

@ -36,7 +36,7 @@ struct ip_addr_encap {
extern int ip_convert_to_binary(const char* text_addr, struct ip_addr_encap* raw);
extern char* ip_convert_to_string(struct ip_addr_encap* raw);
extern const char* ip_convert_to_string(struct ip_addr_encap* raw);
/*

View File

@ -70,7 +70,7 @@ void hub_handle_signal(int fd, short events, void* arg)
case SIGUSR2:
hub_log(log_trace, "hub_handle_signal(): caught SIGUSR2");
{
user_manager_stats(hub);
user_manager_print_stats(hub);
}
break;

View File

@ -688,7 +688,7 @@ char* adc_msg_get_argument(struct adc_message* cmd, int offset)
argument[strlen(argument)-1] = 0;
}
if (strlen(argument))
if (*argument)
{
adc_msg_terminate(cmd);
return argument;

View File

@ -38,8 +38,8 @@ char* strip_white_space(char* string)
while (string[0] && is_white_space(string[0])) string++;
if (!strlen(string))
return string;
if (!*string)
return 0;
/* Strip appending whitespace */
pos = &string[strlen(string)-1];
@ -187,7 +187,7 @@ int file_read_lines(const char* file, void* data, file_line_handler_t handler)
while ((pos = strchr(start, '\n')))
{
pos[0] = '\0';
if (strlen(start) > 0)
if (*start)
{
hub_log(log_dump, "Line: %s", start);
if (handler(start, line_count+1, data) < 0)
@ -197,7 +197,7 @@ int file_read_lines(const char* file, void* data, file_line_handler_t handler)
line_count++;
}
if (strlen(start) > 0)
if (*start)
{
buf[strlen(start)] = 0;
hub_log(log_dump, "Line: %s", start);

View File

@ -79,7 +79,7 @@ void net_on_read(int fd, short ev, void *arg)
while ((pos = strchr(start, '\n')))
{
pos[0] = '\0';
if (strlen(start) > 0 && strlen(start) < user->hub->config->max_recv_buffer)
if (*start && strlen(start) < user->hub->config->max_recv_buffer)
{
if (hub_handle_message(user, start, &pos[0]-&start[0]) == -1)
{
@ -176,6 +176,10 @@ void net_on_write(int fd, short ev, void *arg)
{
user->send_queue_size -= ret;
user->send_queue_offset = 0;
assert(user->send_queue_size >= 0);
assert(user->send_queue_offset >= 0);
list_remove(user->send_queue, msg);
if (user_flag_get(user, flag_user_list) && (msg == user->info || user->send_queue_size == 0))
@ -193,6 +197,9 @@ void net_on_write(int fd, short ev, void *arg)
{
user->send_queue_size -= ret;
user->send_queue_offset += ret;
assert(user->send_queue_size >= 0);
assert(user->send_queue_offset >= 0);
break;
}
}

View File

@ -591,19 +591,6 @@ void net_stats_get(struct net_statistics** intermediate, struct net_statistics**
}
void net_stats_report()
{
int factor = (time(NULL) - stats.timestamp);
if (!factor) factor++;
hub_log(log_info, "Statistics NET: tx=%d KB/s, rx=%d KB/s, (acc=%d/cls=%d/err=%d)",
(int) ((stats.tx / factor) / 1024),
(int) ((stats.rx / factor) / 1024),
(int) stats.accept,
(int) stats.closed,
(int) stats.errors);
}
void net_stats_reset()
{
stats_total.tx += stats.tx;
@ -619,8 +606,7 @@ void net_stats_reset()
int net_stats_timeout()
{
/* FIXME: Configurable time for dumping network statistics */
return (time(NULL) - stats.timestamp > 60) ? 1 : 0;
return (difftime(time(NULL), stats.timestamp) > TIMEOUT_STATS) ? 1 : 0;
}

View File

@ -80,6 +80,26 @@ static void queue_command(struct user* user, struct adc_message* msg__, int offs
}
// #define ALWAYS_QUEUE_MESSAGES
static size_t get_max_send_queue(struct hub_info* hub)
{
return MAX(hub->config->max_send_buffer, (hub->config->max_recv_buffer * hub_get_user_count(hub)));
}
/*
* @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 int check_send_queue(struct 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(user->hub))
return -1;
return 1;
}
int route_to_user(struct user* user, struct adc_message* msg)
{
@ -118,24 +138,23 @@ int route_to_user(struct user* user, struct adc_message* msg)
else
#endif
{
if (!user_flag_get(user, flag_user_list) && user->send_queue_size + msg->length > user->hub->config->max_send_buffer && msg->priority >= 0)
ret = check_send_queue(user, msg);
if (ret == -1)
{
/* User is not able to swallow the data, let's cut our losses and disconnect. */
user_disconnect(user, quit_send_queue);
return 0;
}
else
{
if (user->send_queue_size + msg->length > user->hub->config->max_send_buffer_soft && msg->priority >= 0)
{
/* Don't queue this message if it is low priority! */
}
else
else if (ret == 1)
{
/* queue command */
queue_command(user, msg, 0);
if (user->ev_write)
event_add(user->ev_write, NULL);
}
else
{
/* do not queue command as our soft-limits are exceeded */
}
}

View File

@ -113,7 +113,7 @@
#define TIMEOUT_HANDSHAKE 30
#define TIMEOUT_SENDQ 120
#define TIMEOUT_IDLE 7200
#define TIMEOUT_STATS 3600
#define TIMEOUT_STATS 60
#define MAX_CLIENTS 512
#define MAX_CID_LEN 39

View File

@ -39,30 +39,40 @@ static void clear_user_list_callback(void* ptr)
}
void user_manager_stats(struct hub_info* hub)
void user_manager_update_stats(struct hub_info* hub)
{
int factor = 0;
const int factor = TIMEOUT_STATS;
struct net_statistics* total;
struct net_statistics* intermediate;
net_stats_get(&intermediate, &total);
factor = (time(NULL) - intermediate->timestamp);
if (!factor) factor++;
hub_log(log_info, "Statistics users=%zu, net_tx=%d KB/s, net_rx=%d KB/s",
hub->users->count,
(int) ((intermediate->tx / factor) / 1024),
(int) ((intermediate->rx / factor) / 1024));
hub->stats.net_tx = (intermediate->tx / factor);
hub->stats.net_rx = (intermediate->rx / factor);
hub->stats.net_tx_peak = MAX(hub->stats.net_tx, hub->stats.net_tx_peak);
hub->stats.net_rx_peak = MAX(hub->stats.net_rx, hub->stats.net_rx_peak);
hub->stats.net_tx_total = total->tx;
hub->stats.net_rx_total = total->rx;
net_stats_reset();
}
void user_manager_print_stats(struct hub_info* hub)
{
hub_log(log_info, "Statistics users=%zu (peak_users=%zu), net_tx=%d KB/s, net_rx=%d KB/s (peak_tx=%d KB/s, peak_rx=%d KB/s)",
hub->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);
}
static void timer_statistics(int fd, short ev, void *arg)
{
struct hub_info* hub = (struct hub_info*) arg;
struct timeval timeout = { TIMEOUT_STATS, 0 };
user_manager_stats(hub);
user_manager_update_stats(hub);
evtimer_set(&hub->ev_timer, timer_statistics, hub);
evtimer_add(&hub->ev_timer, &timeout);
}

View File

@ -45,7 +45,8 @@ extern void user_manager_shutdown(struct hub_info* hub);
/**
* Generate statistics for logfiles.
*/
extern void user_manager_stats(struct hub_info* hub);
extern void user_manager_update_stats(struct hub_info* hub);
extern void user_manager_print_stats(struct hub_info* hub);
/**
* Add a new user to the user manager.