From aa26052479cc95c451e494bc6d157aa99337f572 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Tue, 22 Jun 2010 16:04:33 +0200 Subject: [PATCH] Misc plugin work * Fix crash when unloading plugins. * Fixed plugin loader and plugin unload handler. * Added a new example plugin: mod_logging which logs users logging in and out of the hub to stdout. --- GNUmakefile | 6 ++- src/core/hub.c | 5 +++ src/core/hubevent.c | 10 +++++ src/core/netevent.c | 19 +++++---- src/core/plugininvoke.c | 89 +++++++++++++++++++++++++++++++++++++++ src/core/plugininvoke.h | 46 ++++++++++++++++++++ src/core/pluginloader.c | 6 ++- src/core/pluginloader.h | 3 ++ src/plugin_api/handle.h | 52 +++++++++++++++-------- src/plugins/mod_logging.c | 57 +++++++++++++++++++++++++ src/uhub.h | 1 + 11 files changed, 265 insertions(+), 29 deletions(-) create mode 100644 src/core/plugininvoke.c create mode 100644 src/core/plugininvoke.h create mode 100644 src/plugins/mod_logging.c diff --git a/GNUmakefile b/GNUmakefile index ce1e81e..1407e77 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -146,6 +146,7 @@ libuhub_SOURCES := \ src/core/route.c \ src/core/user.c \ src/core/usermanager.c \ + src/core/plugininvoke.c \ src/core/pluginloader.c \ src/network/backend.c \ src/network/connection.c \ @@ -195,6 +196,9 @@ autotest_OBJECTS = autotest.o plugin_example_SOURCES := src/plugins/mod_example.c plugin_example_TARGET := $(plugin_example_SOURCES:.c=.so) +plugin_logging_SOURCES := src/plugins/mod_logging.c +plugin_logging_TARGET := $(plugin_example_SOURCES:.c=.so) + # Source to objects libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o) @@ -206,7 +210,7 @@ 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_plugins := $(plugin_example_TARGET) +all_plugins := $(plugin_example_TARGET) $(plugin_logging_TARGET) uhub_BINARY=uhub$(BIN_EXT) adcrush_BINARY=adcrush$(BIN_EXT) diff --git a/src/core/hub.c b/src/core/hub.c index 7c7fdf0..d3915bf 100644 --- a/src/core/hub.c +++ b/src/core/hub.c @@ -826,6 +826,11 @@ void hub_plugins_load(struct hub_info* hub) void hub_plugins_unload(struct hub_info* hub) { + if (!hub->plugins || !hub->plugins->loaded) + { + return; + } + struct uhub_plugin_handle* plugin = (struct uhub_plugin_handle*) list_get_first(hub->plugins->loaded); while (plugin) { diff --git a/src/core/hubevent.c b/src/core/hubevent.c index 72cd073..a54bce9 100644 --- a/src/core/hubevent.c +++ b/src/core/hubevent.c @@ -18,6 +18,7 @@ */ #include "uhub.h" +#include "plugin_api/handle.h" static void log_user_login(struct hub_user* u) { @@ -67,6 +68,10 @@ void on_login_success(struct hub_info* hub, struct hub_user* u) /* Print log message */ log_user_login(u); +#ifdef PLUGIN_SUPPORT + plugin_log_user_login_success(hub, u); +#endif + /* Announce new user to all connected users */ if (user_is_logged_in(u)) route_info_message(hub, u); @@ -109,6 +114,11 @@ 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); + +#ifdef PLUGIN_SUPPORT + plugin_log_user_logout(hub, user); +#endif + hub_logout_log(hub, user); } diff --git a/src/core/netevent.c b/src/core/netevent.c index e875bba..37a1964 100644 --- a/src/core/netevent.c +++ b/src/core/netevent.c @@ -175,8 +175,10 @@ 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); +#ifdef PLUGIN_SUPPORT + plugin_st status; +#endif for (;;) { @@ -194,19 +196,18 @@ void net_on_accept(struct net_connection* con, int event, void *arg) } } - 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)) +#ifdef PLUGIN_SUPPORT + status = plugin_check_ip_early(hub, &ipaddr); + if (status == st_deny) { - LOG_INFO("Denied [%s] (IP banned)", addr); + plugin_log_connection_denied(hub, &ipaddr); net_close(fd); continue; } + plugin_log_connection_accepted(hub, &ipaddr); +#endif + probe = probe_create(hub, fd, &ipaddr); if (!probe) { diff --git a/src/core/plugininvoke.c b/src/core/plugininvoke.c new file mode 100644 index 0000000..676e9c8 --- /dev/null +++ b/src/core/plugininvoke.c @@ -0,0 +1,89 @@ +/* + * 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 . + * + */ + +#include "uhub.h" +#include "plugin_api/handle.h" + +#define PLUGIN_INVOKE(HUB, FUNCNAME, CODE) \ + if (HUB->plugins && HUB->plugins->loaded) \ + { \ + struct uhub_plugin_handle* plugin = (struct uhub_plugin_handle*) list_get_first(HUB->plugins->loaded); \ + while (plugin) \ + { \ + if (plugin->funcs.FUNCNAME) \ + CODE \ + plugin = (struct uhub_plugin_handle*) list_get_next(HUB->plugins->loaded); \ + } \ + } + +plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr) +{ + plugin_st status = st_default; + PLUGIN_INVOKE(hub, login_check_ip_early, { + status = plugin->funcs.login_check_ip_early(addr); + if (status != st_default) + break; + }); + return status; +} + +plugin_st plugin_check_ip_late(struct hub_info* hub, struct ip_addr_encap* addr) +{ + plugin_st status = st_default; + PLUGIN_INVOKE(hub, login_check_ip_late, { + status = plugin->funcs.login_check_ip_late(addr); + if (status != st_default) + break; + }); + return status; +} + + +void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* ipaddr) +{ + const char* addr = ip_convert_to_string(ipaddr); + LOG_TRACE("Got connection from %s", addr); +} + +void plugin_log_connection_denied(struct hub_info* hub, struct ip_addr_encap* ipaddr) +{ + const char* addr = ip_convert_to_string(ipaddr); + LOG_INFO("Denied connection from %s", addr); +} + +void plugin_log_user_login_success(struct hub_info* hub, struct hub_user* user) +{ +} + +void plugin_log_user_login_error(struct hub_info* hub, struct hub_user* user) +{ +} + +void plugin_log_user_logout(struct hub_info* hub, struct hub_user* user) +{ +} + + +void convert_user_to_plugin_user(struct plugin_user* puser, struct hub_user* user) +{ + puser->sid = user->id.sid; + puser->nick = user->id.nick; + puser->cid = user->id.cid; + puser->addr = user->id.addr; +} \ No newline at end of file diff --git a/src/core/plugininvoke.h b/src/core/plugininvoke.h new file mode 100644 index 0000000..9b230ae --- /dev/null +++ b/src/core/plugininvoke.h @@ -0,0 +1,46 @@ +/* + * 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 . + * + */ + +#ifndef HAVE_UHUB_PLUGIN_INVOKE_H +#define HAVE_UHUB_PLUGIN_INVOKE_H + +#include "uhub.h" +#include "plugin_api/handle.h" + +#ifdef PLUGIN_SUPPORT + +struct hub_info; +struct ip_addr_encap; + +void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* addr); +void plugin_log_connection_denied(struct hub_info* hub, struct ip_addr_encap* addr); +void plugin_log_user_login_success(struct hub_info* hub, struct hub_user* user); +void plugin_log_user_login_error(struct hub_info* hub, struct hub_user* user); +void plugin_log_user_logout(struct hub_info* hub, struct hub_user* user); + +plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr); +plugin_st plugin_check_ip_late(struct hub_info* hub, struct ip_addr_encap* addr); + +plugin_st plugin_check_nickname_valid(struct hub_info* hub, const char* nick); +plugin_st plugin_check_nickname_reserved(struct hub_info* hub, const char* nick); + + +#endif + +#endif // HAVE_UHUB_PLUGIN_INVOKE_H \ No newline at end of file diff --git a/src/core/pluginloader.c b/src/core/pluginloader.c index ce89286..2bcfe59 100644 --- a/src/core/pluginloader.c +++ b/src/core/pluginloader.c @@ -24,6 +24,7 @@ struct uhub_plugin* plugin_open(const char* filename) { + LOG_TRACE("plugin_open: \"%s\"", filename); #ifdef HAVE_DLOPEN struct uhub_plugin* plugin = (struct uhub_plugin*) hub_malloc_zero(sizeof(struct uhub_plugin)); if (!plugin) @@ -92,7 +93,9 @@ struct uhub_plugin_handle* plugin_load(const char* filename, const char* config) { if (handle->plugin_api_version == PLUGIN_API_VERSION && handle->plugin_funcs_size == sizeof(struct plugin_funcs)) { - LOG_INFO("Loaded plugin: %s: \"%s\", version %s.", filename, handle->name, handle->version); + LOG_INFO("Loaded plugin: %s: %s, version %s.", filename, handle->name, handle->version); + LOG_TRACE("Plugin API version: %d (func table size: " PRINTF_SIZE_T ")", handle->plugin_api_version, handle->plugin_funcs_size); + plugin->unregister = unregister_f; return handle; } else @@ -113,6 +116,7 @@ struct uhub_plugin_handle* plugin_load(const char* filename, const char* config) void plugin_unload(struct uhub_plugin_handle* plugin) { + plugin->handle->unregister(plugin); plugin_close(plugin->handle); } diff --git a/src/core/pluginloader.h b/src/core/pluginloader.h index b9729bd..719f51c 100644 --- a/src/core/pluginloader.h +++ b/src/core/pluginloader.h @@ -20,6 +20,8 @@ #ifndef HAVE_UHUB_PLUGIN_LOADER_H #define HAVE_UHUB_PLUGIN_LOADER_H +#include "plugin_api/handle.h" + #ifdef PLUGIN_SUPPORT struct hub_config; @@ -31,6 +33,7 @@ struct uhub_plugin #ifdef HAVE_DLOPEN void* handle; #endif + plugin_unregister_f unregister; }; struct uhub_plugins diff --git a/src/plugin_api/handle.h b/src/plugin_api/handle.h index 2469123..3472beb 100644 --- a/src/plugin_api/handle.h +++ b/src/plugin_api/handle.h @@ -17,6 +17,9 @@ * */ +#ifndef HAVE_UHUB_PLUGIN_HANDLE_H +#define HAVE_UHUB_PLUGIN_HANDLE_H + #include "system.h" #include "util/ipcalc.h" @@ -45,7 +48,6 @@ enum plugin_status st_default = 0, /* Use default */ st_allow = 1, /* Allow action */ st_deny = -1, /* Deny action */ - st_restrict = -2, /* Further action required */ }; typedef enum plugin_status plugin_st; @@ -69,17 +71,24 @@ struct auth_info enum auth_credentials credentials; }; -typedef plugin_st (*on_connect_t)(struct ip_addr_encap*); typedef plugin_st (*on_chat_msg_t)(struct plugin_user* from, const char* message); typedef plugin_st (*on_private_msg_t)(struct plugin_user* from, struct plugin_user* to, const char* message); typedef plugin_st (*on_search_t)(struct plugin_user* from, const char* data); typedef plugin_st (*on_p2p_connect_t)(struct plugin_user* from, struct plugin_user* to); typedef plugin_st (*on_p2p_revconnect_t)(struct plugin_user* from, struct plugin_user* to); + +typedef void (*on_user_connect_t)(struct ip_addr_encap*); typedef void (*on_user_login_t)(struct plugin_user*); typedef void (*on_user_logout_t)(struct plugin_user*); +typedef void (*on_user_nick_change_t)(struct plugin_user*, const char* new_nick); + +typedef plugin_st (*on_change_nick_t)(struct plugin_user*, const char* new_nick); + +typedef plugin_st (*on_check_ip_early_t)(struct ip_addr_encap*); +typedef plugin_st (*on_check_ip_late_t)(struct ip_addr_encap*); typedef plugin_st (*on_validate_nick_t)(const char* nick); typedef plugin_st (*on_validate_cid_t)(const char* cid); -typedef plugin_st (*on_change_nick_t)(struct plugin_user*, const char* new_nick); + typedef int (*auth_get_user_t)(const char* nickname, struct auth_info* info); typedef plugin_st (*auth_register_user_t)(struct auth_info* user); typedef plugin_st (*auth_update_user_t)(struct auth_info* user); @@ -88,23 +97,28 @@ typedef plugin_st (*auth_delete_user_t)(struct auth_info* user); struct plugin_funcs { // Users logging in and out - on_connect_t on_connect; - on_user_login_t on_user_login; - on_user_logout_t on_user_logout; - on_change_nick_t on_user_change_nick; + on_user_connect_t on_user_connect; /* A user has connected to the hub */ + on_user_login_t on_user_login; /* A user has successfully logged in to the hub */ + on_user_logout_t on_user_logout; /* A user has logged out of the hub (was previously logged in) */ + on_user_nick_change_t on_user_nick_change; /* A user has changed nickname */ - // Activity events - on_chat_msg_t on_chat_msg; - on_private_msg_t on_private_msg; - on_search_t on_search; - on_p2p_connect_t on_p2p_connect; - on_p2p_revconnect_t on_p2p_revconnect; + // Activity events (can be intercepted and refused by a plugin) + on_chat_msg_t on_chat_msg; /* A public chat message is about to be sent (can be intercepted) */ + on_private_msg_t on_private_msg; /* A public chat message is about to be sent (can be intercepted) */ + on_search_t on_search; /* A search is about to be sent (can be intercepted) */ + on_p2p_connect_t on_p2p_connect; /* A user is about to connect to another user (can be intercepted) */ + on_p2p_revconnect_t on_p2p_revconnect; /* A user is about to connect to another user (can be intercepted) */ + + // Authentication actions. + auth_get_user_t auth_get_user; /* Get authentication info from plugin */ + auth_register_user_t auth_register_user; /* Register user */ + auth_update_user_t auth_update_user; /* Update a registered user */ + auth_delete_user_t auth_delete_user; /* Delete a registered user */ + + // Login check functions + on_check_ip_early_t login_check_ip_early; + on_check_ip_late_t login_check_ip_late; - // Authentication - auth_get_user_t auth_get_user; - auth_register_user_t auth_register_user; - auth_update_user_t auth_update_user; - auth_delete_user_t auth_delete_user; }; struct uhub_plugin_handle @@ -135,3 +149,5 @@ extern int plugin_unregister(struct uhub_plugin_handle*); typedef int (*plugin_register_f)(struct uhub_plugin_handle* handle, const char* config); typedef int (*plugin_unregister_f)(struct uhub_plugin_handle*); + +#endif /* HAVE_UHUB_PLUGIN_HANDLE_H */ diff --git a/src/plugins/mod_logging.c b/src/plugins/mod_logging.c new file mode 100644 index 0000000..223d46b --- /dev/null +++ b/src/plugins/mod_logging.c @@ -0,0 +1,57 @@ +/** + * This is a minimal example plugin for uhub. + */ + +// #include "uhub.h" +#include "plugin_api/handle.h" + +struct ip_addr_encap; + +plugin_st log_connect(struct ip_addr_encap* addr) +{ + return st_default; +} + +void log_user_login(struct plugin_user* user) +{ + printf("login: \"%s\"\n", user->nick); +} + +void log_user_logout(struct plugin_user* user) +{ + printf("logout: \"%s\"\n", user->nick); +} + +plugin_st log_change_nick(struct plugin_user* user, const char* new_nick) +{ + printf("\"%s\" -> \"%s\"\n", user->nick, new_nick); + return st_default; +} + + +int plugin_register(struct uhub_plugin_handle* plugin, const char* config) +{ + plugin->name = "Logging plugin"; + plugin->version = "1.0"; + plugin->description = "Logs users entering and leaving the hub."; + plugin->ptr = NULL; + plugin->plugin_api_version = PLUGIN_API_VERSION; + plugin->plugin_funcs_size = sizeof(struct plugin_funcs); + memset(&plugin->funcs, 0, sizeof(struct plugin_funcs)); + + plugin->funcs.on_connect = log_connect; + plugin->funcs.on_user_login = log_user_login; + plugin->funcs.on_user_logout = log_user_logout; + plugin->funcs.on_user_change_nick = log_change_nick; + + puts("* plugin register"); + return 0; +} + +int plugin_unregister(struct uhub_plugin_handle* plugin) +{ + /* No need to do anything! */ + puts("* plugin unregister"); + return 0; +} + diff --git a/src/uhub.h b/src/uhub.h index 17fdc79..e8325bb 100644 --- a/src/uhub.h +++ b/src/uhub.h @@ -86,6 +86,7 @@ extern "C" { #include "core/commands.h" #include "core/inf.h" #include "core/hubevent.h" +#include "core/plugininvoke.h" #include "core/pluginloader.h" #ifdef __cplusplus