diff --git a/src/core/commands.c b/src/core/commands.c index 0830cb2..ead45b1 100644 --- a/src/core/commands.c +++ b/src/core/commands.c @@ -141,7 +141,7 @@ const char* command_get_syntax(struct commands_handler* handler) case 'n': strcat(args, ""); break; case 'c': strcat(args, ""); break; case 'a': strcat(args, ""); break; - case 'M': strcat(args, ""); break; + case 'm': strcat(args, ""); break; } } } @@ -384,6 +384,11 @@ static int command_history(struct hub_info* hub, struct hub_user* user, struct h } 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"); @@ -401,6 +406,43 @@ static int command_history(struct hub_info* hub, struct hub_user* user, struct h return ret; } +static int command_log(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd) +{ + char* buffer; + struct linked_list* messages = hub->logout_info; + struct hub_logout_info* log; + int ret = 0; + char tmp[1024]; + + if (!list_size(messages)) + { + return command_status(hub, user, cmd, "No entries logged."); + } + + buffer = hub_malloc(32 + (list_size(messages) * (sizeof(struct hub_logout_info) + 25))); + if (!buffer) + { + return command_status(hub, user, cmd, "Not enough memory."); + } + + buffer[0] = 0; + strcat(buffer, "Log entries"); + strcat(buffer, "\n"); + + log = (struct hub_logout_info*) list_get_first(messages); + while (log) + { + sprintf(tmp, "%s %s, %s (%s)\n", get_timestamp(log->time), log->cid, log->nick, ip_convert_to_string(&log->addr)); + strcat(buffer, tmp); + log = (struct hub_logout_info*) list_get_next(messages); + } + strcat(buffer, "\n"); + + ret = command_status(hub, user, cmd, buffer); + hub_free(buffer); + return ret; +} + #ifdef CRASH_DEBUG static int command_crash(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd) { @@ -468,7 +510,8 @@ static struct commands_handler command_handlers[] = { { "myip", 4, 0, cred_guest, command_myip, "Show your own IP." }, { "getip", 5, "n", cred_operator, command_getip, "Show IP address for a user" }, { "whoip", 5, "a", cred_operator, command_whoip, "Show users matching IP range" }, - { "broadcast", 9, "M", cred_operator, command_broadcast,"Send a message to all users" }, + { "broadcast", 9, "m", cred_operator, command_broadcast,"Send a message to all users" }, + { "log", 3, 0, cred_operator, command_log, "Display log" }, #ifdef CRASH_DEBUG { "crash", 5, 0, cred_admin, command_crash, "Crash the hub (DEBUG)." }, #endif diff --git a/src/core/config.c b/src/core/config.c index f720246..88b6513 100644 --- a/src/core/config.c +++ b/src/core/config.c @@ -117,6 +117,7 @@ #define DEF_FILE_MOTD "" #define DEF_MAX_USERS 500 #define DEF_MAX_CHAT_HISTORY 20 +#define DEF_MAX_LOGOUT_LOG 100 #define DEF_MAX_RECV_BUFFER 4096 #define DEF_MAX_SEND_BUFFER 131072 #define DEF_MAX_SEND_BUFFER_SOFT 98304 @@ -177,6 +178,7 @@ void config_defaults(struct hub_config* config) DEFAULT_INTEGER(server_port, DEF_SERVER_PORT); 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_send_buffer, DEF_MAX_SEND_BUFFER); DEFAULT_INTEGER(max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT); @@ -248,6 +250,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li GET_BOOL(hub_enabled); GET_INT (max_users); GET_INT (max_chat_history); + GET_INT (max_logout_log); GET_INT (max_recv_buffer); GET_INT (max_send_buffer); GET_INT (max_send_buffer_soft); @@ -395,6 +398,7 @@ void dump_config(struct hub_config* config, int ignore_defaults) DUMP_BOOL(hub_enabled, DEF_HUB_ENABLED); DUMP_INT (max_users, DEF_MAX_USERS); DUMP_INT (max_chat_history, DEF_MAX_CHAT_HISTORY); + DUMP_INT (max_logout_log, DEF_MAX_LOGOUT_LOG); DUMP_INT (max_recv_buffer, DEF_MAX_RECV_BUFFER); DUMP_INT (max_send_buffer, DEF_MAX_SEND_BUFFER); DUMP_INT (max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT); diff --git a/src/core/config.h b/src/core/config.h index f909bc0..8a7da9c 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -40,6 +40,7 @@ struct hub_config int low_bandwidth_mode; /**<<< "If this is enabled, the hub will strip off elements from each user's info message to reduce bandwidth usage" */ int max_chat_history; /**<<< "Number of chat messages kept in history (default: 20)" */ + int max_logout_log; /**<<< "Number of log entries for people leaving the hub. (default: 100) */ /* Limits enforced on users */ int limit_max_hubs_user; /**<<< "Max concurrent hubs as a user. (0=off, default: 10)" */ diff --git a/src/core/hub.c b/src/core/hub.c index fe685ad..53bef53 100644 --- a/src/core/hub.c +++ b/src/core/hub.c @@ -200,7 +200,6 @@ int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc hub_chat_history_add(hub, u, cmd); ret = route_message(hub, u, cmd); } - hub_free(message); return ret; } @@ -209,9 +208,7 @@ void hub_chat_history_add(struct hub_info* hub, struct hub_user* user, struct ad { char* message = adc_msg_get_argument(cmd, 0); char* log = hub_malloc(strlen(message) + strlen(user->id.nick) + 14); - time_t now = time(NULL); - struct tm* t = localtime(&now); - sprintf(log, "[%02d:%02d] <%s> %s\n", t->tm_hour, t->tm_min, user->id.nick, message); + sprintf(log, "%s <%s> %s\n", get_timestamp(time(NULL)), user->id.nick, message); list_append(hub->chat_history, log); while (list_size(hub->chat_history) > (size_t) hub->config->max_chat_history) { @@ -550,8 +547,11 @@ struct hub_info* hub_start_service(struct hub_config* config) } hub->chat_history = (struct linked_list*) list_create(); + hub->logout_info = (struct linked_list*) list_create(); if (!hub->chat_history) { + list_destroy(hub->chat_history); + list_destroy(hub->logout_info); hub_free(hub->recvbuf); hub_free(hub->sendbuf); uman_shutdown(hub); @@ -581,6 +581,8 @@ void hub_shutdown_service(struct hub_info* hub) hub_free(hub->recvbuf); hub_chat_history_clear(hub); list_destroy(hub->chat_history); + list_clear(hub->logout_info, &hub_free); + list_destroy(hub->logout_info); hub_free(hub); hub = 0; g_hub = 0; @@ -989,3 +991,22 @@ void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int reason } } +void hub_logout_log(struct hub_info* hub, struct hub_user* user) +{ + struct hub_logout_info* loginfo = hub_malloc_zero(sizeof(struct hub_logout_info)); + if (!loginfo) return; + loginfo->time = time(NULL); + strcpy(loginfo->cid, user->id.cid); + strcpy(loginfo->nick, user->id.nick); + memcpy(&loginfo->addr, &user->net.ipaddr, sizeof(struct ip_addr_encap)); + loginfo->reason = user->quit_reason; + + list_append(hub->logout_info, loginfo); + while (list_size(hub->logout_info) > (size_t) hub->config->max_logout_log) + { + struct hub_logout_info* entry = list_get_first(hub->logout_info); + list_remove(hub->logout_info, entry); + hub_free(entry); + } +} + diff --git a/src/core/hub.h b/src/core/hub.h index 51fd74d..6a28222 100644 --- a/src/core/hub.h +++ b/src/core/hub.h @@ -79,6 +79,15 @@ struct hub_stats 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; + int reason; +}; + struct hub_info { int fd_tcp; @@ -100,6 +109,7 @@ struct hub_info 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 SSL_METHOD* ssl_method; @@ -343,6 +353,10 @@ extern void hub_schedule_destroy_user(struct hub_info* hub, struct hub_user* use */ 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 */ diff --git a/src/core/hubevent.c b/src/core/hubevent.c index c47f93d..35a43d1 100644 --- a/src/core/hubevent.c +++ b/src/core/hubevent.c @@ -114,6 +114,7 @@ void on_logout_user(struct hub_info* hub, struct hub_user* user) } log_user_logout(user, reason); + hub_logout_log(hub, user); user->quit_reason = 0; } diff --git a/src/util/misc.c b/src/util/misc.c index 3240da5..63ec011 100644 --- a/src/util/misc.c +++ b/src/util/misc.c @@ -361,3 +361,10 @@ int split_string(const char* string, const char* split, struct linked_list* list 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; +} diff --git a/src/util/misc.h b/src/util/misc.h index 6e38bcb..3f49432 100644 --- a/src/util/misc.h +++ b/src/util/misc.h @@ -22,6 +22,8 @@ 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_space(char c); extern int is_white_space(char c);