diff --git a/src/admin.c b/src/admin.c index 9e02d8ed..e1823306 100644 --- a/src/admin.c +++ b/src/admin.c @@ -46,6 +46,8 @@ #define CATMODULE "admin" +#define ADMIN_MAX_COMMAND_TABLES 8 + /* Helper macros */ #define COMMAND_REQUIRE(client,name,var) \ do { \ @@ -94,15 +96,6 @@ #define DEFAULT_TRANSFORMED_REQUEST "" #define BUILDM3U_RAW_REQUEST "buildm3u" -typedef void (*request_function_ptr)(client_t *, source_t *, admin_format_t); - -typedef struct admin_command_handler { - const char *route; - const int type; - const int format; - const request_function_ptr function; -} admin_command_handler_t; - typedef struct { const char *prefix; size_t length; @@ -157,7 +150,7 @@ static const admin_command_handler_t handlers[] = { { DEFAULT_RAW_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_TRANSFORMED, command_stats } }; -static admin_command_table_t command_tables[] = { +static admin_command_table_t command_tables[ADMIN_MAX_COMMAND_TABLES] = { {.prefix = NULL, .length = (sizeof(handlers)/sizeof(*handlers)), .handlers = handlers}, }; @@ -288,6 +281,41 @@ int admin_get_command_type(admin_command_id_t command) return ADMINTYPE_ERROR; } +int admin_command_table_register(const char *prefix, size_t handlers_length, const admin_command_handler_t *handlers) +{ + size_t i; + + if (prefix == NULL || handlers_length == 0 || handlers == NULL) + return -1; + + for (i = 0; i < (sizeof(command_tables)/sizeof(*command_tables)); i++) { + if (__is_command_table_valid(&(command_tables[i]))) + continue; + + command_tables[i].prefix = prefix; + command_tables[i].length = handlers_length; + command_tables[i].handlers = handlers; + + return 0; + } + + return -1; +} + +int admin_command_table_unregister(const char *prefix) +{ + size_t i; + + for (i = 0; i < (sizeof(command_tables)/sizeof(*command_tables)); i++) { + if (command_tables[i].prefix != NULL && strcmp(command_tables[i].prefix, prefix) == 0) { + memset(&(command_tables[i]), 0, sizeof(command_tables[i])); + return 0; + } + } + + return -1; +} + /* build an XML doc containing information about currently running sources. * If a mountpoint is passed then that source will not be added to the XML * doc even if the source is running */ diff --git a/src/admin.h b/src/admin.h index 3de9a1f5..d0770414 100644 --- a/src/admin.h +++ b/src/admin.h @@ -45,6 +45,15 @@ typedef enum { #define ADMIN_COMMAND_ERROR ((admin_command_id_t)(-1)) #define ADMIN_COMMAND_ANY ((admin_command_id_t)0) /* for ACL framework */ +typedef void (*admin_request_function_ptr)(client_t * client, source_t * source, admin_format_t format); + +typedef struct admin_command_handler { + const char *route; + const int type; + const int format; + const admin_request_function_ptr function; +} admin_command_handler_t; + void admin_handle_request(client_t *client, const char *uri); void admin_send_response(xmlDocPtr doc, @@ -61,4 +70,10 @@ xmlNodePtr admin_add_role_to_authentication(auth_t *auth, xmlNodePtr parent); admin_command_id_t admin_get_command(const char *command); int admin_get_command_type(admin_command_id_t command); +/* Register and unregister admin commands below /admin/$prefix/. + * All parameters must be kept in memory as long as the registration is valid as there will be no copy made. + */ +int admin_command_table_register(const char *prefix, size_t handlers_length, const admin_command_handler_t *handlers); +int admin_command_table_unregister(const char *prefix); + #endif /* __ADMIN_H__ */