mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-12-04 14:46:30 -05:00
Feature: Set foundation for having multiple admin/ sub-directories
This commit is contained in:
parent
9fb26c4607
commit
86154bc6d9
@ -31,7 +31,7 @@ struct acl_tag {
|
|||||||
|
|
||||||
/* admin/ interface */
|
/* admin/ interface */
|
||||||
struct {
|
struct {
|
||||||
int command;
|
admin_command_id_t command;
|
||||||
acl_policy_t policy;
|
acl_policy_t policy;
|
||||||
} admin_commands[MAX_ADMIN_COMMANDS];
|
} admin_commands[MAX_ADMIN_COMMANDS];
|
||||||
size_t admin_commands_len;
|
size_t admin_commands_len;
|
||||||
@ -253,7 +253,7 @@ int acl_set_admin_str__callbck(acl_t *acl,
|
|||||||
const char *str)
|
const char *str)
|
||||||
{
|
{
|
||||||
size_t read_i, write_i;
|
size_t read_i, write_i;
|
||||||
int command = admin_get_command(str);
|
admin_command_id_t command = admin_get_command(str);
|
||||||
|
|
||||||
if (command == ADMIN_COMMAND_ERROR)
|
if (command == ADMIN_COMMAND_ERROR)
|
||||||
return -1;
|
return -1;
|
||||||
@ -279,7 +279,7 @@ int acl_set_admin_str__callbck(acl_t *acl,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
acl_policy_t acl_test_admin(acl_t *acl, int command)
|
acl_policy_t acl_test_admin(acl_t *acl, admin_command_id_t command)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
@ -18,6 +18,11 @@
|
|||||||
#include <libxml/tree.h>
|
#include <libxml/tree.h>
|
||||||
#include "common/httpp/httpp.h"
|
#include "common/httpp/httpp.h"
|
||||||
|
|
||||||
|
struct acl_tag;
|
||||||
|
typedef struct acl_tag acl_t;
|
||||||
|
|
||||||
|
#include "admin.h"
|
||||||
|
|
||||||
typedef enum acl_policy_tag {
|
typedef enum acl_policy_tag {
|
||||||
/* Error on function call */
|
/* Error on function call */
|
||||||
ACL_POLICY_ERROR = -1,
|
ACL_POLICY_ERROR = -1,
|
||||||
@ -27,8 +32,6 @@ typedef enum acl_policy_tag {
|
|||||||
ACL_POLICY_DENY = 1
|
ACL_POLICY_DENY = 1
|
||||||
} acl_policy_t;
|
} acl_policy_t;
|
||||||
|
|
||||||
struct acl_tag;
|
|
||||||
typedef struct acl_tag acl_t;
|
|
||||||
|
|
||||||
/* basic functions to work with ACLs */
|
/* basic functions to work with ACLs */
|
||||||
acl_t * acl_new(void);
|
acl_t * acl_new(void);
|
||||||
@ -48,7 +51,7 @@ acl_policy_t acl_test_method(acl_t * acl, httpp_request_type_e method);
|
|||||||
/* admin/ interface specific functions */
|
/* admin/ interface specific functions */
|
||||||
int acl_set_admin_str__callbck(acl_t * acl, acl_policy_t policy, const char * str);
|
int acl_set_admin_str__callbck(acl_t * acl, acl_policy_t policy, const char * str);
|
||||||
#define acl_set_admin_str(acl,policy,str) acl_set_ANY_str((acl), (policy), (str), acl_set_admin_str__callbck)
|
#define acl_set_admin_str(acl,policy,str) acl_set_ANY_str((acl), (policy), (str), acl_set_admin_str__callbck)
|
||||||
acl_policy_t acl_test_admin(acl_t * acl, int command);
|
acl_policy_t acl_test_admin(acl_t * acl, admin_command_id_t command);
|
||||||
|
|
||||||
/* web/ interface specific functions */
|
/* web/ interface specific functions */
|
||||||
int acl_set_web_policy(acl_t * acl, acl_policy_t policy);
|
int acl_set_web_policy(acl_t * acl, acl_policy_t policy);
|
||||||
|
103
src/admin.c
103
src/admin.c
@ -103,6 +103,12 @@ typedef struct admin_command_handler {
|
|||||||
const request_function_ptr function;
|
const request_function_ptr function;
|
||||||
} admin_command_handler_t;
|
} admin_command_handler_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *prefix;
|
||||||
|
size_t length;
|
||||||
|
const admin_command_handler_t *handlers;
|
||||||
|
} admin_command_table_t;
|
||||||
|
|
||||||
static void command_fallback (client_t *client, source_t *source, admin_format_t response);
|
static void command_fallback (client_t *client, source_t *source, admin_format_t response);
|
||||||
static void command_metadata (client_t *client, source_t *source, admin_format_t response);
|
static void command_metadata (client_t *client, source_t *source, admin_format_t response);
|
||||||
static void command_shoutcast_metadata (client_t *client, source_t *source, admin_format_t response);
|
static void command_shoutcast_metadata (client_t *client, source_t *source, admin_format_t response);
|
||||||
@ -151,33 +157,108 @@ static const admin_command_handler_t handlers[] = {
|
|||||||
{ DEFAULT_RAW_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_TRANSFORMED, command_stats }
|
{ DEFAULT_RAW_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_TRANSFORMED, command_stats }
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HANDLERS_COUNT (sizeof(handlers)/sizeof(*handlers))
|
static admin_command_table_t command_tables[] = {
|
||||||
|
{.prefix = NULL, .length = (sizeof(handlers)/sizeof(*handlers)), .handlers = handlers},
|
||||||
|
};
|
||||||
|
|
||||||
int admin_get_command(const char *command)
|
static inline const admin_command_table_t * admin_get_table(admin_command_id_t command)
|
||||||
|
{
|
||||||
|
size_t t = (command & 0x00FF0000) >> 16;
|
||||||
|
|
||||||
|
if (t >= (sizeof(command_tables)/sizeof(*command_tables)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &(command_tables[t]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const admin_command_table_t * admin_get_table_by_prefix(const char *command)
|
||||||
|
{
|
||||||
|
const char *end;
|
||||||
|
size_t i;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
end = strchr(command, '/');
|
||||||
|
|
||||||
|
if (end == NULL) {
|
||||||
|
for (i = 0; i < (sizeof(command_tables)/sizeof(*command_tables)); i++)
|
||||||
|
if (command_tables[i].prefix == NULL)
|
||||||
|
return &(command_tables[i]);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = end - command;
|
||||||
|
|
||||||
|
for (i = 0; i < (sizeof(command_tables)/sizeof(*command_tables)); i++) {
|
||||||
|
if (command_tables[i].prefix != NULL && strlen(command_tables[i].prefix) == len && strncmp(command_tables[i].prefix, command, len) == 0) {
|
||||||
|
return &(command_tables[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline admin_command_id_t admin_get_command_by_table_and_index(const admin_command_table_t *table, size_t index)
|
||||||
|
{
|
||||||
|
size_t t = table - command_tables;
|
||||||
|
|
||||||
|
if (t >= (sizeof(command_tables)/sizeof(*command_tables)))
|
||||||
|
return ADMIN_COMMAND_ERROR;
|
||||||
|
|
||||||
|
if (index > 0x0FFFF)
|
||||||
|
return ADMIN_COMMAND_ERROR;
|
||||||
|
|
||||||
|
return (t << 16) | index;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t admin_get_index_by_command(admin_command_id_t command)
|
||||||
|
{
|
||||||
|
return command & 0x0FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
admin_command_id_t admin_get_command(const char *command)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
const admin_command_table_t *table = admin_get_table_by_prefix(command);
|
||||||
|
const char *suffix;
|
||||||
|
|
||||||
for (i = 0; i < HANDLERS_COUNT; i++)
|
if (table == NULL)
|
||||||
if (strcmp(handlers[i].route, command) == 0)
|
return COMMAND_ERROR;
|
||||||
return i;
|
|
||||||
|
suffix = strchr(command, '/');
|
||||||
|
if (suffix != NULL) {
|
||||||
|
suffix++;
|
||||||
|
} else {
|
||||||
|
suffix = command;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < table->length; i++)
|
||||||
|
if (strcmp(table->handlers[i].route, suffix) == 0)
|
||||||
|
return admin_get_command_by_table_and_index(table, i);
|
||||||
|
|
||||||
return COMMAND_ERROR;
|
return COMMAND_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the command handler for command or NULL
|
/* Get the command handler for command or NULL
|
||||||
*/
|
*/
|
||||||
const admin_command_handler_t* admin_get_handler(int command)
|
const admin_command_handler_t* admin_get_handler(admin_command_id_t command)
|
||||||
{
|
{
|
||||||
if (command > 0 && command < HANDLERS_COUNT)
|
const admin_command_table_t *table = admin_get_table(command);
|
||||||
return &handlers[command];
|
size_t index = admin_get_index_by_command(command);
|
||||||
|
|
||||||
return NULL;
|
if (table == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (index >= table->length)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &(table->handlers[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the command type for command
|
/* Get the command type for command
|
||||||
* If the command is invalid, ADMINTYPE_ERROR is returned.
|
* If the command is invalid, ADMINTYPE_ERROR is returned.
|
||||||
*/
|
*/
|
||||||
int admin_get_command_type(int command)
|
int admin_get_command_type(admin_command_id_t command)
|
||||||
{
|
{
|
||||||
const admin_command_handler_t* handler = admin_get_handler(command);
|
const admin_command_handler_t* handler = admin_get_handler(command);
|
||||||
|
|
||||||
@ -350,7 +431,7 @@ void admin_handle_request(client_t *client, const char *uri)
|
|||||||
handler = admin_get_handler(client->admin_command);
|
handler = admin_get_handler(client->admin_command);
|
||||||
|
|
||||||
/* Check if admin command is valid */
|
/* Check if admin command is valid */
|
||||||
if (handler == NULL) {
|
if (handler == NULL || handler->function == NULL) {
|
||||||
ICECAST_LOG_ERROR("Error parsing command string or unrecognised command: %H",
|
ICECAST_LOG_ERROR("Error parsing command string or unrecognised command: %H",
|
||||||
uri);
|
uri);
|
||||||
client_send_error_by_id(client, ICECAST_ERROR_ADMIN_UNRECOGNISED_COMMAND);
|
client_send_error_by_id(client, ICECAST_ERROR_ADMIN_UNRECOGNISED_COMMAND);
|
||||||
|
13
src/admin.h
13
src/admin.h
@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
#include <libxml/parser.h>
|
#include <libxml/parser.h>
|
||||||
#include <libxml/tree.h>
|
#include <libxml/tree.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Command IDs */
|
||||||
|
typedef int32_t admin_command_id_t;
|
||||||
|
|
||||||
/* formats */
|
/* formats */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -25,6 +29,7 @@ typedef enum {
|
|||||||
ADMIN_FORMAT_PLAINTEXT
|
ADMIN_FORMAT_PLAINTEXT
|
||||||
} admin_format_t;
|
} admin_format_t;
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
#include "refbuf.h"
|
#include "refbuf.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "source.h"
|
#include "source.h"
|
||||||
@ -37,8 +42,8 @@ typedef enum {
|
|||||||
#define ADMINTYPE_HYBRID (ADMINTYPE_GENERAL|ADMINTYPE_MOUNT)
|
#define ADMINTYPE_HYBRID (ADMINTYPE_GENERAL|ADMINTYPE_MOUNT)
|
||||||
|
|
||||||
/* special commands */
|
/* special commands */
|
||||||
#define ADMIN_COMMAND_ERROR (-1)
|
#define ADMIN_COMMAND_ERROR ((admin_command_id_t)(-1))
|
||||||
#define ADMIN_COMMAND_ANY 0 /* for ACL framework */
|
#define ADMIN_COMMAND_ANY ((admin_command_id_t)0) /* for ACL framework */
|
||||||
|
|
||||||
void admin_handle_request(client_t *client, const char *uri);
|
void admin_handle_request(client_t *client, const char *uri);
|
||||||
|
|
||||||
@ -53,7 +58,7 @@ void admin_add_listeners_to_mount(source_t *source,
|
|||||||
|
|
||||||
xmlNodePtr admin_add_role_to_authentication(auth_t *auth, xmlNodePtr parent);
|
xmlNodePtr admin_add_role_to_authentication(auth_t *auth, xmlNodePtr parent);
|
||||||
|
|
||||||
int admin_get_command(const char *command);
|
admin_command_id_t admin_get_command(const char *command);
|
||||||
int admin_get_command_type(int command);
|
int admin_get_command_type(admin_command_id_t command);
|
||||||
|
|
||||||
#endif /* __ADMIN_H__ */
|
#endif /* __ADMIN_H__ */
|
||||||
|
@ -46,8 +46,7 @@ typedef enum _reuse_tag {
|
|||||||
ICECAST_REUSE_UPGRADETLS
|
ICECAST_REUSE_UPGRADETLS
|
||||||
} reuse_t;
|
} reuse_t;
|
||||||
|
|
||||||
struct _client_tag
|
struct _client_tag {
|
||||||
{
|
|
||||||
/* mode of operation for this client */
|
/* mode of operation for this client */
|
||||||
operation_mode mode;
|
operation_mode mode;
|
||||||
|
|
||||||
@ -70,7 +69,7 @@ struct _client_tag
|
|||||||
int respcode;
|
int respcode;
|
||||||
|
|
||||||
/* admin command if any. ADMIN_COMMAND_ERROR if not an admin command. */
|
/* admin command if any. ADMIN_COMMAND_ERROR if not an admin command. */
|
||||||
int admin_command;
|
admin_command_id_t admin_command;
|
||||||
|
|
||||||
/* authentication instances we still need to go thru */
|
/* authentication instances we still need to go thru */
|
||||||
struct auth_stack_tag *authstack;
|
struct auth_stack_tag *authstack;
|
||||||
@ -110,7 +109,6 @@ struct _client_tag
|
|||||||
|
|
||||||
/* function to check if refbuf needs updating */
|
/* function to check if refbuf needs updating */
|
||||||
int (*check_buffer)(struct source_tag *source, struct _client_tag *client);
|
int (*check_buffer)(struct source_tag *source, struct _client_tag *client);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int client_create (client_t **c_ptr, connection_t *con, http_parser_t *parser);
|
int client_create (client_t **c_ptr, connection_t *con, http_parser_t *parser);
|
||||||
|
@ -61,7 +61,7 @@ struct event_tag {
|
|||||||
char *client_role; /* from client->role */
|
char *client_role; /* from client->role */
|
||||||
char *client_username; /* from client->username */
|
char *client_username; /* from client->username */
|
||||||
char *client_useragent; /* from httpp_getvar(client->parser, "user-agent") */
|
char *client_useragent; /* from httpp_getvar(client->parser, "user-agent") */
|
||||||
int client_admin_command; /* from client->admin_command */
|
admin_command_id_t client_admin_command; /* from client->admin_command */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct event_registration_tag {
|
struct event_registration_tag {
|
||||||
|
@ -25,8 +25,7 @@ typedef struct source_tag source_t;
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
struct source_tag
|
struct source_tag {
|
||||||
{
|
|
||||||
mutex_t lock;
|
mutex_t lock;
|
||||||
client_t *client;
|
client_t *client;
|
||||||
connection_t *con;
|
connection_t *con;
|
||||||
@ -83,7 +82,6 @@ struct source_tag
|
|||||||
refbuf_t *stream_data_tail;
|
refbuf_t *stream_data_tail;
|
||||||
|
|
||||||
playlist_t *history;
|
playlist_t *history;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
source_t *source_reserve (const char *mount);
|
source_t *source_reserve (const char *mount);
|
||||||
|
Loading…
Reference in New Issue
Block a user