1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-06-23 06:25:24 +00:00

Merge branch 'feature-ping' into devel

This commit is contained in:
Philipp Schafft 2023-03-04 11:54:39 +00:00
commit 28b4ff2d55
5 changed files with 195 additions and 50 deletions

View File

@ -45,6 +45,7 @@ noinst_HEADERS = \
fastevent.h \
navigation.h \
event.h \
ping.h \
acl.h auth.h \
metadata_xiph.h \
format.h \
@ -121,6 +122,7 @@ icecast_SOURCES = \
if HAVE_CURL
icecast_SOURCES += \
curl.c \
ping.c \
auth_url.c \
event_url.c
endif
@ -143,6 +145,7 @@ endif
EXTRA_icecast_SOURCES = \
curl.c \
ping.c \
yp.c \
auth_url.c \
event_url.c \

View File

@ -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"
@ -31,23 +31,10 @@ typedef struct event_url {
bool legacy;
char *url;
char *action;
char *userpwd;
CURL *handle;
char errormsg[CURL_ERROR_SIZE];
char *username;
char *password;
} 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;
@ -92,18 +79,7 @@ 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);
} 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);
@ -112,17 +88,15 @@ 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->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 +118,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) {
@ -157,27 +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);
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;

View File

@ -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();

161
src/ping.c Normal file
View File

@ -0,0 +1,161 @@
/* Icecast
*
* Copyright 2023 Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
*
* 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 <config.h>
#endif
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "thread/thread.h"
#include "ping.h"
#include "logging.h"
#include "curl.h"
#define CATMODULE "ping"
typedef struct ping_queue_tag ping_queue_t;
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 cond_t ping_cond;
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) {
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) {
if (!ping_running)
break;
thread_cond_wait(&ping_cond);
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);
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);
thread_cond_broadcast(&ping_cond);
}
void ping_simple(const char *url, const char *username, const char *password, const char *data)
{
ping_queue_t *entry = calloc(1, sizeof(*entry));
if (!entry)
return;
entry->curl = icecast_curl_new(url, NULL);
if (!entry->curl) {
free(entry);
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);
}
void ping_initialize(void)
{
if (ping_running)
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);
}
void ping_shutdown(void)
{
if (!ping_running)
return;
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!");
}

17
src/ping.h Normal file
View File

@ -0,0 +1,17 @@
/* Icecast
*
* Copyright 2023 Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
*
* 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__
void ping_initialize(void);
void ping_shutdown(void);
void ping_simple(const char *url, const char *username, const char *password, const char *data);
#endif /* __PING_H__ */