From 57ba8c2297015765992f30eae8a52bb3b99dc22a Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Sat, 17 Sep 2022 16:53:38 +0000 Subject: [PATCH] Feature: Added uniform way to include event data in log and URL event backend --- src/event.c | 27 ++++++++++++++++++++++ src/event.h | 3 +++ src/event_log.c | 31 +++++++++++++++---------- src/event_url.c | 60 +++++++++++++++++++++++++++---------------------- 4 files changed, 82 insertions(+), 39 deletions(-) diff --git a/src/event.c b/src/event.c index 214c25e6..ed6f5090 100644 --- a/src/event.c +++ b/src/event.c @@ -22,6 +22,7 @@ #include "event.h" #include "fastevent.h" #include "logging.h" +#include "string_renderer.h" #include "admin.h" #include "connection.h" #include "client.h" @@ -90,6 +91,32 @@ const char * event_extra_key_name(event_extra_key_t key) return NULL; } +igloo_error_t event_to_string_renderer(const event_t *event, string_renderer_t *renderer) +{ + static const event_extra_key_t key_list[] = { + EVENT_EXTRA_KEY_URI, + EVENT_EXTRA_KEY_SOURCE_MEDIA_TYPE, + EVENT_EXTRA_KEY_CONNECTION_IP, + EVENT_EXTRA_KEY_CLIENT_ROLE, + EVENT_EXTRA_KEY_CLIENT_USERNAME, + EVENT_EXTRA_KEY_CLIENT_USERAGENT, + EVENT_EXTRA_LIST_END + }; + + string_renderer_add_kv_with_options(renderer, "trigger", event->trigger, STRING_RENDERER_ENCODING_PLAIN, false, false); + for (size_t i = 0; key_list[i] != EVENT_EXTRA_LIST_END; i++) { + string_renderer_add_kv_with_options(renderer, event_extra_key_name(key_list[i]), event_extra_get(event, key_list[i]), STRING_RENDERER_ENCODING_PLAIN, false, false); + } + + if (event->client_data) { + string_renderer_add_ki_with_options(renderer, "connection-id", event->connection_id, STRING_RENDERER_ENCODING_PLAIN, true, false); + string_renderer_add_ki_with_options(renderer, "connection-time", event->connection_time, STRING_RENDERER_ENCODING_PLAIN, true, false); + string_renderer_add_ki_with_options(renderer, "client-admin-command", event->client_admin_command, STRING_RENDERER_ENCODING_PLAIN, true, false); + } + + return igloo_ERROR_NONE; +} + /* work with event_t* */ static void event_addref(event_t *event) { if (!event) diff --git a/src/event.h b/src/event.h index 25ae2e5e..59289d39 100644 --- a/src/event.h +++ b/src/event.h @@ -15,6 +15,8 @@ #include #include +#include + #include "common/thread/thread.h" #include "icecasttypes.h" @@ -125,6 +127,7 @@ void event_emit_va(const char *trigger, ...); /* reading extra from events */ const char * event_extra_get(const event_t *event, const event_extra_key_t key); const char * event_extra_key_name(event_extra_key_t key); +igloo_error_t event_to_string_renderer(const event_t *event, string_renderer_t *renderer); /* expects renderer in list mode */ /* Implementations */ int event_get_exec(event_registration_t *er, config_options_t *options); diff --git a/src/event_log.c b/src/event_log.c index 6b38db51..5b069243 100644 --- a/src/event_log.c +++ b/src/event_log.c @@ -12,7 +12,13 @@ #include +#include "icecasttypes.h" +#include +#include + #include "event.h" +#include "global.h" /* for igloo_instance */ +#include "string_renderer.h" #include "util.h" #include "cfgfile.h" #include "logging.h" @@ -24,23 +30,24 @@ typedef struct event_log { int level; } event_log_t; + static int event_log_emit(void *state, event_t *event) { event_log_t *self = state; + string_renderer_t * renderer; + + if (igloo_ro_new(&renderer, string_renderer_t, igloo_instance) != igloo_ERROR_NONE) + return 0; + + string_renderer_start_list(renderer, " ", "=", false, false, STRING_RENDERER_ENCODING_H_ALT_SPACE); + event_to_string_renderer(event, renderer); + string_renderer_end_list(renderer); ICECAST_LOG(self->level, ICECAST_LOGFLAG_NONE, - "%s%strigger=%# H uri=%#H " - "connection_id=%lu connection_ip=%#H connection_time=%lli " - "client_role=%# H client_username=%#H client_useragent=%# H client_admin_command=%i source_media_type=%#H", + "%s%s%s", self->prefix ? self->prefix : "", self->prefix ? ": " : "", - event->trigger, - event_extra_get(event, EVENT_EXTRA_KEY_URI), - event->connection_id, event_extra_get(event, EVENT_EXTRA_KEY_CONNECTION_IP), (long long int)event->connection_time, - event_extra_get(event, EVENT_EXTRA_KEY_CLIENT_ROLE), - event_extra_get(event, EVENT_EXTRA_KEY_CLIENT_USERNAME), - event_extra_get(event, EVENT_EXTRA_KEY_CLIENT_USERAGENT), - event->client_admin_command, - event_extra_get(event, EVENT_EXTRA_KEY_SOURCE_MEDIA_TYPE) - ); + string_renderer_to_string_zero_copy(renderer)); + + igloo_ro_unref(&renderer); return 0; } diff --git a/src/event_url.c b/src/event_url.c index 33d9377b..37b05322 100644 --- a/src/event_url.c +++ b/src/event_url.c @@ -12,6 +12,12 @@ #include +#include "icecasttypes.h" +#include +#include + +#include "global.h" /* for igloo_instance */ +#include "string_renderer.h" #include "curl.h" #include "event.h" #include "cfgfile.h" @@ -43,43 +49,41 @@ static inline char *__escape(const char *src, const char *default_value) { static int event_url_emit(void *state, event_t *event) { event_url_t *self = state; ice_config_t *config; - char *action, *mount, *server, *role, *username, *ip, *agent, *media_type; time_t duration; - char post[4096]; + string_renderer_t * renderer; - action = util_url_escape(self->action ? self->action : event->trigger); - mount = __escape(event_extra_get(event, EVENT_EXTRA_KEY_URI), ""); - role = __escape(event_extra_get(event, EVENT_EXTRA_KEY_CLIENT_ROLE), ""); - username = __escape(event_extra_get(event, EVENT_EXTRA_KEY_CLIENT_USERNAME), ""); - ip = __escape(event_extra_get(event, EVENT_EXTRA_KEY_CONNECTION_IP), ""); - agent = __escape(event_extra_get(event, EVENT_EXTRA_KEY_CLIENT_USERAGENT), "-"); - media_type = __escape(event_extra_get(event, EVENT_EXTRA_KEY_CLIENT_USERAGENT), "-"); + if (igloo_ro_new(&renderer, string_renderer_t, igloo_instance) != igloo_ERROR_NONE) + return 0; - if (event->connection_time) { + if (event->client_data) { duration = time(NULL) - event->connection_time; } else { duration = 0; } - config = config_get_config(); - server = __escape(config->hostname, ""); + string_renderer_start_list_formdata(renderer); + /* Old style */ + string_renderer_add_kv_with_options(renderer, "action", self->action ? self->action : event->trigger, STRING_RENDERER_ENCODING_PLAIN, false, false); + string_renderer_add_kv_with_options(renderer, "mount", event_extra_get(event, EVENT_EXTRA_KEY_URI), STRING_RENDERER_ENCODING_PLAIN, true, true); + string_renderer_add_ki_with_options(renderer, "client", event->connection_id, STRING_RENDERER_ENCODING_PLAIN, true, true); + string_renderer_add_kv_with_options(renderer, "role", event_extra_get(event, EVENT_EXTRA_KEY_CLIENT_ROLE), STRING_RENDERER_ENCODING_PLAIN, true, true); + string_renderer_add_kv_with_options(renderer, "username", event_extra_get(event, EVENT_EXTRA_KEY_CLIENT_USERNAME), STRING_RENDERER_ENCODING_PLAIN, true, true); + string_renderer_add_kv_with_options(renderer, "ip", event_extra_get(event, EVENT_EXTRA_KEY_CONNECTION_IP), STRING_RENDERER_ENCODING_PLAIN, true, true); + string_renderer_add_kv_with_options(renderer, "agent", event_extra_get(event, EVENT_EXTRA_KEY_CLIENT_USERAGENT) ? event_extra_get(event, EVENT_EXTRA_KEY_CLIENT_USERAGENT) : "-", STRING_RENDERER_ENCODING_PLAIN, true, true); + string_renderer_add_ki_with_options(renderer, "duration", duration, STRING_RENDERER_ENCODING_PLAIN, true, true); + string_renderer_add_ki_with_options(renderer, "admin", event->client_admin_command, STRING_RENDERER_ENCODING_PLAIN, true, true); - snprintf (post, sizeof (post), - "action=%s&mount=%s&server=%s&port=%d&client=%lu&role=%s&username=%s&ip=%s&agent=%s&duration=%lli&admin=%i&source-media-type=%s", - action, mount, server, config->port, - event->connection_id, role, username, ip, agent, (long long int)duration, event->client_admin_command, - media_type - ); + /* new style */ + event_to_string_renderer(event, renderer); + + /* common */ + config = config_get_config(); + string_renderer_add_kv_with_options(renderer, "server", config->hostname, STRING_RENDERER_ENCODING_PLAIN, true, true); + string_renderer_add_ki_with_options(renderer, "port", config->port, STRING_RENDERER_ENCODING_PLAIN, true, true); config_release_config(); - free(action); - free(mount); - free(server); - free(role); - free(username); - free(ip); - free(agent); - free(media_type); + string_renderer_end_list(renderer); + if (strchr(self->url, '@') == NULL && self->userpwd) { curl_easy_setopt(self->handle, CURLOPT_USERPWD, self->userpwd); @@ -88,11 +92,13 @@ static int event_url_emit(void *state, event_t *event) { } curl_easy_setopt(self->handle, CURLOPT_URL, self->url); - curl_easy_setopt(self->handle, CURLOPT_POSTFIELDS, post); + curl_easy_setopt(self->handle, CURLOPT_POSTFIELDS, string_renderer_to_string_zero_copy(renderer)); if (curl_easy_perform(self->handle)) ICECAST_LOG_WARN("auth to server %s failed with %s", self->url, self->errormsg); + igloo_ro_unref(&renderer); + return 0; }