From e3f9f5b078e3f1fc33b2f3344d2c3255f979737e Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Sun, 26 Feb 2023 21:30:37 +0000 Subject: [PATCH 1/7] Feature: Added stub for ping requests --- src/Makefile.am | 2 ++ src/ping.c | 14 ++++++++++++++ src/ping.h | 12 ++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 src/ping.c create mode 100644 src/ping.h diff --git a/src/Makefile.am b/src/Makefile.am index 936345f9..b6239d71 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -45,6 +45,7 @@ noinst_HEADERS = \ fastevent.h \ navigation.h \ event.h \ + ping.h \ acl.h auth.h \ metadata_xiph.h \ format.h \ @@ -111,6 +112,7 @@ icecast_SOURCES = \ event.c \ event_log.c \ event_exec.c \ + ping.c \ acl.c \ auth.c \ auth_htpasswd.c \ diff --git a/src/ping.c b/src/ping.c new file mode 100644 index 00000000..d010d257 --- /dev/null +++ b/src/ping.c @@ -0,0 +1,14 @@ +/* Icecast + * + * Copyright 2023 Philipp "ph3-der-loewe" Schafft + * + * This program is distributed under the GNU General Public License, version 2. + * A copy of this license is included with this source. + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "ping.h" diff --git a/src/ping.h b/src/ping.h new file mode 100644 index 00000000..8c3dec1c --- /dev/null +++ b/src/ping.h @@ -0,0 +1,12 @@ +/* Icecast + * + * Copyright 2023 Philipp "ph3-der-loewe" Schafft + * + * This program is distributed under the GNU General Public License, version 2. + * A copy of this license is included with this source. + */ + +#ifndef __PING_H__ +#define __PING_H__ + +#endif /* __PING_H__ */ From 53055aafd7ff0f26d0f6b87498ef8141a4f436ce Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Sun, 26 Feb 2023 21:33:40 +0000 Subject: [PATCH 2/7] Update: Made ping depend on CURL support --- src/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index b6239d71..2be43133 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -112,7 +112,6 @@ icecast_SOURCES = \ event.c \ event_log.c \ event_exec.c \ - ping.c \ acl.c \ auth.c \ auth_htpasswd.c \ @@ -123,6 +122,7 @@ icecast_SOURCES = \ if HAVE_CURL icecast_SOURCES += \ curl.c \ + ping.c \ auth_url.c \ event_url.c endif @@ -145,6 +145,7 @@ endif EXTRA_icecast_SOURCES = \ curl.c \ + ping.c \ yp.c \ auth_url.c \ event_url.c \ From 91ea5d0f79f72eb3f20e41df42440ad9b932ce50 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Sun, 26 Feb 2023 21:47:18 +0000 Subject: [PATCH 3/7] Feature: Added most basic ping infrastructure --- src/main.c | 5 +++++ src/ping.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ src/ping.h | 3 +++ 3 files changed, 55 insertions(+) diff --git a/src/main.c b/src/main.c index 7bbb36c3..3ce3eb22 100644 --- a/src/main.c +++ b/src/main.c @@ -82,6 +82,7 @@ #include "yp.h" #include "auth.h" #include "event.h" +#include "ping.h" #include "listensocket.h" #include "fastevent.h" #include "prng.h" @@ -169,6 +170,7 @@ static void initialize_subsystems(void) xslt_initialize(); #ifdef HAVE_CURL icecast_curl_initialize(); + ping_initialize(); #endif } @@ -182,6 +184,9 @@ static void shutdown_subsystems(void) auth_shutdown(); yp_shutdown(); stats_shutdown(); +#ifdef HAVE_CURL + ping_shutdown(); +#endif ICECAST_LOG_DEBUG("Shuting down connection related subsystems..."); connection_shutdown(); diff --git a/src/ping.c b/src/ping.c index d010d257..8e9d2e66 100644 --- a/src/ping.c +++ b/src/ping.c @@ -11,4 +11,51 @@ #include #endif +#include + +#include "thread/thread.h" + #include "ping.h" +#include "logging.h" +#include "curl.h" + +#define CATMODULE "ping" + +static bool ping_running = false; +static thread_type *_ping_thread_id; +static mutex_t _ping_mutex; + +static void *_ping_thread(void *arg) +{ + CURLM *curl_multi = curl_multi_init(); + + while (ping_running) { + break; + } + + curl_multi_cleanup(curl_multi); + + return NULL; +} + +void ping_initialize(void) +{ + if (ping_running) + return; + + thread_mutex_create(&_ping_mutex); + + ping_running = true; + _ping_thread_id = thread_create("Ping Thread", _ping_thread, NULL, THREAD_ATTACHED); +} + +void ping_shutdown(void) +{ + if (!ping_running) + return; + + ping_running = false; + ICECAST_LOG_DEBUG("waiting for ping thread"); + thread_join(_ping_thread_id); + thread_mutex_destroy(&_ping_mutex); +} diff --git a/src/ping.h b/src/ping.h index 8c3dec1c..53870979 100644 --- a/src/ping.h +++ b/src/ping.h @@ -9,4 +9,7 @@ #ifndef __PING_H__ #define __PING_H__ +void ping_initialize(void); +void ping_shutdown(void); + #endif /* __PING_H__ */ From 3c352746abfef7a87df91f588624af1978cfd284 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Mon, 27 Feb 2023 01:21:29 +0000 Subject: [PATCH 4/7] Feature: Added basic ping request support --- src/ping.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++------ src/ping.h | 2 ++ 2 files changed, 94 insertions(+), 10 deletions(-) diff --git a/src/ping.c b/src/ping.c index 8e9d2e66..ad462b6d 100644 --- a/src/ping.c +++ b/src/ping.c @@ -12,6 +12,7 @@ #endif #include +#include #include "thread/thread.h" @@ -21,16 +22,72 @@ #define CATMODULE "ping" -static bool ping_running = false; -static thread_type *_ping_thread_id; -static mutex_t _ping_mutex; +typedef struct ping_queue_tag ping_queue_t; -static void *_ping_thread(void *arg) +struct ping_queue_tag { + CURL *curl; + ping_queue_t *next; +}; + +static bool ping_running = false; +static thread_type *ping_thread_id; +static mutex_t ping_mutex; +static ping_queue_t *ping_queue; + +static void on_done(ping_queue_t *entry) +{ + icecast_curl_free(entry->curl); + free(entry); +} + +static void *ping_thread(void *arg) { CURLM *curl_multi = curl_multi_init(); while (ping_running) { - break; + ping_queue_t *take; + int status; + + thread_mutex_lock(&ping_mutex); + take = ping_queue; + ping_queue = NULL; + thread_mutex_unlock(&ping_mutex); + + while (take) { + ping_queue_t *entry = take; + + take = take->next; + entry->next = NULL; + + curl_easy_setopt(entry->curl, CURLOPT_PRIVATE, entry); + curl_multi_add_handle(curl_multi, entry->curl); + } + + if (curl_multi_perform(curl_multi, &status) != CURLM_OK) + break; + + if (!status) { + thread_sleep(100000); + continue; + } + + if (curl_multi_wait(curl_multi, NULL, 0, 1000, &status) != CURLM_OK) + break; + + while (true) { + struct CURLMsg *m = curl_multi_info_read(curl_multi, &status); + + if (!m) + break; + + if (m->msg == CURLMSG_DONE) { + ping_queue_t *entry = NULL; + CURL *e = m->easy_handle; + curl_multi_remove_handle(curl_multi, e); + curl_easy_getinfo(e, CURLINFO_PRIVATE, &entry); + on_done(entry); + } + } } curl_multi_cleanup(curl_multi); @@ -38,15 +95,39 @@ static void *_ping_thread(void *arg) return NULL; } +static void ping_add_to_queue(ping_queue_t *entry) +{ + thread_mutex_lock(&ping_mutex); + entry->next = ping_queue; + ping_queue = entry; + thread_mutex_unlock(&ping_mutex); +} + +void ping_simple(const char *url) +{ + ping_queue_t *entry = calloc(1, sizeof(*entry)); + + if (!entry) + return; + + entry->curl = icecast_curl_new(url, NULL); + if (!entry->curl) { + free(entry); + return; + } + + ping_add_to_queue(entry); +} + void ping_initialize(void) { if (ping_running) return; - thread_mutex_create(&_ping_mutex); + thread_mutex_create(&ping_mutex); ping_running = true; - _ping_thread_id = thread_create("Ping Thread", _ping_thread, NULL, THREAD_ATTACHED); + ping_thread_id = thread_create("Ping Thread", ping_thread, NULL, THREAD_ATTACHED); } void ping_shutdown(void) @@ -55,7 +136,8 @@ void ping_shutdown(void) return; ping_running = false; - ICECAST_LOG_DEBUG("waiting for ping thread"); - thread_join(_ping_thread_id); - thread_mutex_destroy(&_ping_mutex); + ICECAST_LOG_DEBUG("Waiting for ping thread"); + thread_join(ping_thread_id); + thread_mutex_destroy(&ping_mutex); + ICECAST_LOG_DEBUG("Joined ping thread, good job!"); } diff --git a/src/ping.h b/src/ping.h index 53870979..913aabf5 100644 --- a/src/ping.h +++ b/src/ping.h @@ -12,4 +12,6 @@ void ping_initialize(void); void ping_shutdown(void); +void ping_simple(const char *url); + #endif /* __PING_H__ */ From 4cea6372ac10beb34e551b00d587e7ce871c35da Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Mon, 27 Feb 2023 01:46:07 +0000 Subject: [PATCH 5/7] Cleanup: Simplified URL event credential code --- src/event_url.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/src/event_url.c b/src/event_url.c index b501dd43..08388868 100644 --- a/src/event_url.c +++ b/src/event_url.c @@ -31,7 +31,8 @@ typedef struct event_url { bool legacy; char *url; char *action; - char *userpwd; + char *username; + char *password; CURL *handle; char errormsg[CURL_ERROR_SIZE]; } event_url_t; @@ -93,8 +94,9 @@ static int event_url_emit(void *state, event_t *event) { string_renderer_end_list(renderer); - if (strchr(self->url, '@') == NULL && self->userpwd) { - curl_easy_setopt(self->handle, CURLOPT_USERPWD, self->userpwd); + if (strchr(self->url, '@') == NULL && self->username && self->password) { + curl_easy_setopt(self->handle, CURLOPT_USERNAME, self->username); + curl_easy_setopt(self->handle, CURLOPT_PASSWORD, self->password); } else { curl_easy_setopt(self->handle, CURLOPT_USERPWD, ""); } @@ -115,14 +117,13 @@ static void event_url_free(void *state) { icecast_curl_free(self->handle); free(self->url); free(self->action); - free(self->userpwd); + free(self->username); + free(self->password); free(self); } int event_get_url(event_registration_t *er, config_options_t *options) { event_url_t *self = calloc(1, sizeof(event_url_t)); - const char *username = NULL; - const char *password = NULL; if (!self) return -1; @@ -144,9 +145,9 @@ int event_get_url(event_registration_t *er, config_options_t *options) { if (strcmp(options->name, "url") == 0) { util_replace_string(&(self->url), options->value); } else if (strcmp(options->name, "username") == 0) { - username = options->value; + util_replace_string(&(self->username), options->value); } else if (strcmp(options->name, "password") == 0) { - password = options->value; + util_replace_string(&(self->password), options->value); } else if (strcmp(options->name, "action") == 0) { util_replace_string(&(self->action), options->value); } else if (strcmp(options->name, "legacy") == 0) { @@ -168,16 +169,6 @@ int event_get_url(event_registration_t *er, config_options_t *options) { curl_easy_setopt(self->handle, CURLOPT_HEADERFUNCTION, handle_returned); curl_easy_setopt(self->handle, CURLOPT_ERRORBUFFER, self->errormsg); - if (username && password) { - size_t len = strlen(username) + strlen(password) + 2; - self->userpwd = malloc(len); - if (!self->userpwd) { - event_url_free(self); - return -1; - } - snprintf(self->userpwd, len, "%s:%s", username, password); - } - er->state = self; er->emit = event_url_emit; er->free = event_url_free; From 8a308f2e12ab920bf0a35d903291a6be38c8ce7c Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Mon, 27 Feb 2023 02:01:41 +0000 Subject: [PATCH 6/7] Feature: Use ping requests for URL events --- src/event_url.c | 38 +++----------------------------------- src/ping.c | 13 ++++++++++++- src/ping.h | 2 +- 3 files changed, 16 insertions(+), 37 deletions(-) diff --git a/src/event_url.c b/src/event_url.c index 08388868..6fb9c775 100644 --- a/src/event_url.c +++ b/src/event_url.c @@ -19,7 +19,7 @@ #include "global.h" /* for igloo_instance */ #include "string_renderer.h" -#include "curl.h" +#include "ping.h" #include "event.h" #include "cfgfile.h" #include "util.h" @@ -33,22 +33,8 @@ typedef struct event_url { char *action; char *username; char *password; - CURL *handle; - char errormsg[CURL_ERROR_SIZE]; } event_url_t; -static size_t handle_returned (void *ptr, size_t size, size_t nmemb, void *stream) { - (void)ptr, (void)stream; - return size * nmemb; -} - -static inline char *__escape(const char *src, const char *default_value) { - if (src) - return util_url_escape(src); - - return strdup(default_value); -} - static int event_url_emit(void *state, event_t *event) { event_url_t *self = state; ice_config_t *config; @@ -93,19 +79,7 @@ static int event_url_emit(void *state, event_t *event) { string_renderer_end_list(renderer); - - if (strchr(self->url, '@') == NULL && self->username && self->password) { - curl_easy_setopt(self->handle, CURLOPT_USERNAME, self->username); - curl_easy_setopt(self->handle, CURLOPT_PASSWORD, self->password); - } else { - curl_easy_setopt(self->handle, CURLOPT_USERPWD, ""); - } - - curl_easy_setopt(self->handle, CURLOPT_URL, self->url); - 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); + ping_simple(self->url, self->username, self->password, string_renderer_to_string_zero_copy(renderer)); igloo_ro_unref(&renderer); @@ -114,7 +88,6 @@ static int event_url_emit(void *state, event_t *event) { static void event_url_free(void *state) { event_url_t *self = state; - icecast_curl_free(self->handle); free(self->url); free(self->action); free(self->username); @@ -158,17 +131,12 @@ int event_get_url(event_registration_t *er, config_options_t *options) { } while ((options = options->next)); } - self->handle = icecast_curl_new(NULL, NULL); - /* check if we are in sane state */ - if (!self->url || !self->handle) { + if (!self->url) { event_url_free(self); return -1; } - curl_easy_setopt(self->handle, CURLOPT_HEADERFUNCTION, handle_returned); - curl_easy_setopt(self->handle, CURLOPT_ERRORBUFFER, self->errormsg); - er->state = self; er->emit = event_url_emit; er->free = event_url_free; diff --git a/src/ping.c b/src/ping.c index ad462b6d..2a46a5b9 100644 --- a/src/ping.c +++ b/src/ping.c @@ -13,6 +13,7 @@ #include #include +#include #include "thread/thread.h" @@ -103,7 +104,7 @@ static void ping_add_to_queue(ping_queue_t *entry) thread_mutex_unlock(&ping_mutex); } -void ping_simple(const char *url) +void ping_simple(const char *url, const char *username, const char *password, const char *data) { ping_queue_t *entry = calloc(1, sizeof(*entry)); @@ -116,6 +117,16 @@ void ping_simple(const char *url) return; } + if (strchr(url, '@') == NULL) { + if (username) + curl_easy_setopt(entry->curl, CURLOPT_USERNAME, username); + if (password) + curl_easy_setopt(entry->curl, CURLOPT_PASSWORD, password); + } + + if (data) + curl_easy_setopt(entry->curl, CURLOPT_COPYPOSTFIELDS, data); + ping_add_to_queue(entry); } diff --git a/src/ping.h b/src/ping.h index 913aabf5..78bc9fff 100644 --- a/src/ping.h +++ b/src/ping.h @@ -12,6 +12,6 @@ void ping_initialize(void); void ping_shutdown(void); -void ping_simple(const char *url); +void ping_simple(const char *url, const char *username, const char *password, const char *data); #endif /* __PING_H__ */ From a27a97012f4255d62b6d089c62cc8230a3d62921 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Mon, 27 Feb 2023 02:19:43 +0000 Subject: [PATCH 7/7] Update: Replaced sleep with a condition wait in ping thread --- src/ping.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ping.c b/src/ping.c index 2a46a5b9..31bcd097 100644 --- a/src/ping.c +++ b/src/ping.c @@ -34,6 +34,7 @@ static bool ping_running = false; static thread_type *ping_thread_id; static mutex_t ping_mutex; static ping_queue_t *ping_queue; +static cond_t ping_cond; static void on_done(ping_queue_t *entry) { @@ -68,7 +69,9 @@ static void *ping_thread(void *arg) break; if (!status) { - thread_sleep(100000); + if (!ping_running) + break; + thread_cond_wait(&ping_cond); continue; } @@ -102,6 +105,7 @@ static void ping_add_to_queue(ping_queue_t *entry) entry->next = ping_queue; ping_queue = entry; thread_mutex_unlock(&ping_mutex); + thread_cond_broadcast(&ping_cond); } void ping_simple(const char *url, const char *username, const char *password, const char *data) @@ -136,6 +140,7 @@ void ping_initialize(void) return; thread_mutex_create(&ping_mutex); + thread_cond_create(&ping_cond); ping_running = true; ping_thread_id = thread_create("Ping Thread", ping_thread, NULL, THREAD_ATTACHED); @@ -148,7 +153,9 @@ void ping_shutdown(void) ping_running = false; ICECAST_LOG_DEBUG("Waiting for ping thread"); + thread_cond_broadcast(&ping_cond); thread_join(ping_thread_id); thread_mutex_destroy(&ping_mutex); + thread_cond_destroy(&ping_cond); ICECAST_LOG_DEBUG("Joined ping thread, good job!"); }