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