1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2025-01-03 14:56:34 -05:00

Update: Reimplemented extra information stored in events in a nicer way

This commit is contained in:
Philipp Schafft 2022-09-06 12:31:11 +00:00
parent a76aa28201
commit aab5e5d2b3
5 changed files with 108 additions and 38 deletions

View File

@ -15,6 +15,9 @@
#include <stdlib.h>
#include <stdbool.h>
#include <igloo/error.h>
#include <igloo/sp.h>
#include "event.h"
#include "fastevent.h"
#include "logging.h"
@ -22,6 +25,7 @@
#include "connection.h"
#include "client.h"
#include "cfgfile.h"
#include "global.h" /* for igloo_instance */
#define CATMODULE "event"
@ -31,6 +35,42 @@ static bool event_running = false;
static thread_type *event_thread = NULL;
static cond_t cond;
/* ignores errors */
static void extra_add(event_t *event, event_extra_key_t key, const char *value)
{
if (!value)
return;
if (event->extra_fill == event->extra_size) {
event_extra_entry_t *n = realloc(event->extra_entries, sizeof(*n)*(event->extra_size + 16));
if (!n)
return;
memset(&(n[event->extra_size]), 0, sizeof(*n)*16);
event->extra_size += 16;
event->extra_entries = n;
}
if (igloo_sp_replace(value, &(event->extra_entries[event->extra_fill].value), igloo_instance) == igloo_ERROR_NONE) {
event->extra_entries[event->extra_fill].key = key;
event->extra_fill++;
}
}
const char * event_extra_get(const event_t *event, const event_extra_key_t key)
{
size_t i;
if (!event || !event->extra_entries)
return NULL;
for (i = 0; i < event->extra_fill; i++) {
if (event->extra_entries[i].key == key)
return event->extra_entries[i].value;
}
return NULL;
}
/* work with event_t* */
static void event_addref(event_t *event) {
if (!event)
@ -58,11 +98,11 @@ static void event_release(event_t *event) {
event_registration_release(event->reglist[i]);
free(event->trigger);
free(event->uri);
free(event->connection_ip);
free(event->client_role);
free(event->client_username);
free(event->client_useragent);
for (i = 0; i < event->extra_fill; i++)
igloo_sp_unref(&(event->extra_entries[i].value), igloo_instance);
free(event->extra_entries);
to_free = event->next;
free(event);
thread_mutex_unlock(&event_lock);
@ -403,22 +443,17 @@ void event_emit_clientevent(const char *trigger, client_t *client, const char *u
#endif
if (client) {
const char *tmp;
event->connection_id = client->con->id;
event->connection_time = client->con->con_time;
event->client_admin_command = client->admin_command;
event->connection_ip = strdup(client->con->ip);
if (client->role)
event->client_role = strdup(client->role);
if (client->username)
event->client_username = strdup(client->username);
tmp = httpp_getvar(client->parser, "user-agent");
if (tmp)
event->client_useragent = strdup(tmp);
extra_add(event, EVENT_EXTRA_CONNECTION_IP, client->con->ip);
extra_add(event, EVENT_EXTRA_CLIENT_ROLE, client->role);
extra_add(event, EVENT_EXTRA_CLIENT_USERNAME, client->username);
extra_add(event, EVENT_EXTRA_CLIENT_USERAGENT, httpp_getvar(client->parser, "user-agent"));
}
if (uri)
event->uri = strdup(uri);
extra_add(event, EVENT_EXTRA_KEY_URI, uri);
event_emit(event);
event_release(event);

View File

@ -25,6 +25,19 @@
#define MAX_REGLISTS_PER_EVENT 8
typedef enum {
EVENT_EXTRA_KEY_URI,
EVENT_EXTRA_CONNECTION_IP,
EVENT_EXTRA_CLIENT_ROLE,
EVENT_EXTRA_CLIENT_USERNAME,
EVENT_EXTRA_CLIENT_USERAGENT
} event_extra_key_t;
typedef struct {
event_extra_key_t key;
const char *value;
} event_extra_entry_t;
struct event_registration_tag;
typedef struct event_registration_tag event_registration_t;
@ -49,14 +62,13 @@ struct event_tag {
char *trigger;
/* from client */
char *uri; /* from context */
unsigned long connection_id; /* from client->con->id */
char *connection_ip; /* from client->con->ip */
time_t connection_time; /* from client->con->con_time */
char *client_role; /* from client->role */
char *client_username; /* from client->username */
char *client_useragent; /* from httpp_getvar(client->parser, "user-agent") */
admin_command_id_t client_admin_command; /* from client->admin_command */
/* extra */
size_t extra_size;
size_t extra_fill;
event_extra_entry_t *extra_entries;
};
struct event_registration_tag {
@ -100,6 +112,9 @@ void event_registration_push(event_registration_t **er, event_registration_t *ta
void event_emit_clientevent(const char *trigger, client_t *client, const char *uri);
#define event_emit_global(x) event_emit_clientevent((x), NULL, NULL)
/* reading extra from events */
const char * event_extra_get(const event_t *event, const event_extra_key_t key);
/* Implementations */
int event_get_exec(event_registration_t *er, config_options_t *options);
int event_get_url(event_registration_t *er, config_options_t *options);

View File

@ -46,6 +46,13 @@ typedef struct event_exec {
char **argv;
} event_exec_t;
static char *_null_aware_strdup(const char *s)
{
if (!s)
return NULL;
return strdup(s);
}
/* OS independed code: */
static inline size_t __argvtype2offset(event_exec_argvtype_t argvtype) {
switch (argvtype) {
@ -79,6 +86,8 @@ static inline event_exec_argvtype_t __str2argvtype(const char *str) {
}
static inline char **__setup_argv(event_exec_t *self, event_t *event) {
char *uri;
self->argv[0] = self->executable;
switch (self->argvtype) {
@ -89,14 +98,16 @@ static inline char **__setup_argv(event_exec_t *self, event_t *event) {
self->argv[2] = event->trigger ? event->trigger : "";
/* fall through */
case ARGVTYPE_ONLY_URI:
self->argv[1] = event->uri ? event->uri : "";
uri = _null_aware_strdup(event_extra_get(event, EVENT_EXTRA_KEY_URI));
self->argv[1] = uri ? uri : "";
break;
case ARGVTYPE_LEGACY:
/* This mode is similar to ARGVTYPE_ONLY_URI
* but if URI is unknown the parameter is skipped!
*/
if (event->uri) {
self->argv[1] = event->uri;
uri = _null_aware_strdup(event_extra_get(event, EVENT_EXTRA_KEY_URI));
if (uri) {
self->argv[1] = uri;
} else {
self->argv[1] = self->executable;
return &self->argv[1];
@ -122,6 +133,12 @@ static inline void __update_environ(const char *name, const char *value) {
#else
#define __update_environ(x,y)
#endif
static inline void __update_environ_with_key(const event_t *event, const char *name, event_extra_key_t key)
{
__update_environ(name, event_extra_get(event, key));
}
static inline void __setup_environ(ice_config_t *config, event_exec_t *self, event_t *event) {
mount_proxy *mountinfo;
source_t *source;
@ -132,13 +149,13 @@ static inline void __setup_environ(ice_config_t *config, event_exec_t *self, eve
__update_environ("ICECAST_HOSTNAME", config->hostname);
__update_environ("ICECAST_ADMIN", config->admin);
__update_environ("ICECAST_LOGDIR", config->log_dir);
__update_environ("EVENT_URI", event->uri);
__update_environ("EVENT_TRIGGER", event->trigger); /* new name */
__update_environ("SOURCE_ACTION", event->trigger); /* old name (deprecated) */
__update_environ("CLIENT_IP", event->connection_ip);
__update_environ("CLIENT_ROLE", event->client_role);
__update_environ("CLIENT_USERNAME", event->client_username);
__update_environ("CLIENT_USERAGENT", event->client_useragent);
__update_environ_with_key(event, "EVENT_URI", EVENT_EXTRA_KEY_URI);
__update_environ_with_key(event, "CLIENT_IP", EVENT_EXTRA_CONNECTION_IP);
__update_environ_with_key(event, "CLIENT_ROLE", EVENT_EXTRA_CLIENT_ROLE);
__update_environ_with_key(event, "CLIENT_USERNAME", EVENT_EXTRA_CLIENT_USERNAME);
__update_environ_with_key(event, "CLIENT_USERAGENT", EVENT_EXTRA_CLIENT_USERAGENT);
snprintf(buf, sizeof(buf), "%lu", event->connection_id);
__update_environ("CLIENT_ID", buf);
@ -147,7 +164,7 @@ static inline void __setup_environ(ice_config_t *config, event_exec_t *self, eve
snprintf(buf, sizeof(buf), "%i", event->client_admin_command);
__update_environ("CLIENT_ADMIN_COMMAND", buf);
mountinfo = config_find_mount(config, event->uri, MOUNT_TYPE_NORMAL);
mountinfo = config_find_mount(config, event_extra_get(event, EVENT_EXTRA_KEY_URI), MOUNT_TYPE_NORMAL);
if (mountinfo) {
__update_environ("MOUNT_NAME", mountinfo->stream_name);
__update_environ("MOUNT_DESCRIPTION", mountinfo->stream_description);
@ -156,7 +173,7 @@ static inline void __setup_environ(ice_config_t *config, event_exec_t *self, eve
}
avl_tree_rlock(global.source_tree);
source = source_find_mount(event->uri);
source = source_find_mount(event_extra_get(event, EVENT_EXTRA_KEY_URI));
if (source) {
__update_environ("SOURCE_MOUNTPOINT", source->mount);
__update_environ("SOURCE_PUBLIC", source->yp_public ? "true" : "false");

View File

@ -33,9 +33,12 @@ static int event_log_emit(void *state, event_t *event) {
"client_role=%# H client_username=%#H client_useragent=%# H client_admin_command=%i",
self->prefix ? self->prefix : "", self->prefix ? ": " : "",
event->trigger,
event->uri,
event->connection_id, event->connection_ip, (long long int)event->connection_time,
event->client_role, event->client_username, event->client_useragent, event->client_admin_command);
event_extra_get(event, EVENT_EXTRA_KEY_URI),
event->connection_id, event_extra_get(event, EVENT_EXTRA_CONNECTION_IP), (long long int)event->connection_time,
event_extra_get(event, EVENT_EXTRA_CLIENT_ROLE),
event_extra_get(event, EVENT_EXTRA_CLIENT_USERNAME),
event_extra_get(event, EVENT_EXTRA_CLIENT_USERAGENT),
event->client_admin_command);
return 0;
}

View File

@ -48,11 +48,11 @@ static int event_url_emit(void *state, event_t *event) {
char post[4096];
action = util_url_escape(self->action ? self->action : event->trigger);
mount = __escape(event->uri, "");
role = __escape(event->client_role, "");
username = __escape(event->client_username, "");
ip = __escape(event->connection_ip, "");
agent = __escape(event->client_useragent, "-");
mount = __escape(event_extra_get(event, EVENT_EXTRA_KEY_URI), "");
role = __escape(event_extra_get(event, EVENT_EXTRA_CLIENT_ROLE), "");
username = __escape(event_extra_get(event, EVENT_EXTRA_CLIENT_USERNAME), "");
ip = __escape(event_extra_get(event, EVENT_EXTRA_CONNECTION_IP), "");
agent = __escape(event_extra_get(event, EVENT_EXTRA_CLIENT_USERAGENT), "-");
if (event->connection_time) {
duration = time(NULL) - event->connection_time;