mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-12-04 14:46:30 -05:00
Merge branch 'feature-ping' into devel
This commit is contained in:
commit
28b4ff2d55
@ -45,6 +45,7 @@ noinst_HEADERS = \
|
|||||||
fastevent.h \
|
fastevent.h \
|
||||||
navigation.h \
|
navigation.h \
|
||||||
event.h \
|
event.h \
|
||||||
|
ping.h \
|
||||||
acl.h auth.h \
|
acl.h auth.h \
|
||||||
metadata_xiph.h \
|
metadata_xiph.h \
|
||||||
format.h \
|
format.h \
|
||||||
@ -121,6 +122,7 @@ icecast_SOURCES = \
|
|||||||
if HAVE_CURL
|
if HAVE_CURL
|
||||||
icecast_SOURCES += \
|
icecast_SOURCES += \
|
||||||
curl.c \
|
curl.c \
|
||||||
|
ping.c \
|
||||||
auth_url.c \
|
auth_url.c \
|
||||||
event_url.c
|
event_url.c
|
||||||
endif
|
endif
|
||||||
@ -143,6 +145,7 @@ endif
|
|||||||
|
|
||||||
EXTRA_icecast_SOURCES = \
|
EXTRA_icecast_SOURCES = \
|
||||||
curl.c \
|
curl.c \
|
||||||
|
ping.c \
|
||||||
yp.c \
|
yp.c \
|
||||||
auth_url.c \
|
auth_url.c \
|
||||||
event_url.c \
|
event_url.c \
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#include "global.h" /* for igloo_instance */
|
#include "global.h" /* for igloo_instance */
|
||||||
#include "string_renderer.h"
|
#include "string_renderer.h"
|
||||||
#include "curl.h"
|
#include "ping.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "cfgfile.h"
|
#include "cfgfile.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@ -31,23 +31,10 @@ typedef struct event_url {
|
|||||||
bool legacy;
|
bool legacy;
|
||||||
char *url;
|
char *url;
|
||||||
char *action;
|
char *action;
|
||||||
char *userpwd;
|
char *username;
|
||||||
CURL *handle;
|
char *password;
|
||||||
char errormsg[CURL_ERROR_SIZE];
|
|
||||||
} event_url_t;
|
} 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) {
|
static int event_url_emit(void *state, event_t *event) {
|
||||||
event_url_t *self = state;
|
event_url_t *self = state;
|
||||||
ice_config_t *config;
|
ice_config_t *config;
|
||||||
@ -92,18 +79,7 @@ static int event_url_emit(void *state, event_t *event) {
|
|||||||
|
|
||||||
string_renderer_end_list(renderer);
|
string_renderer_end_list(renderer);
|
||||||
|
|
||||||
|
ping_simple(self->url, self->username, self->password, string_renderer_to_string_zero_copy(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);
|
|
||||||
|
|
||||||
igloo_ro_unref(&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) {
|
static void event_url_free(void *state) {
|
||||||
event_url_t *self = state;
|
event_url_t *self = state;
|
||||||
icecast_curl_free(self->handle);
|
|
||||||
free(self->url);
|
free(self->url);
|
||||||
free(self->action);
|
free(self->action);
|
||||||
free(self->userpwd);
|
free(self->username);
|
||||||
|
free(self->password);
|
||||||
free(self);
|
free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
int event_get_url(event_registration_t *er, config_options_t *options) {
|
int event_get_url(event_registration_t *er, config_options_t *options) {
|
||||||
event_url_t *self = calloc(1, sizeof(event_url_t));
|
event_url_t *self = calloc(1, sizeof(event_url_t));
|
||||||
const char *username = NULL;
|
|
||||||
const char *password = NULL;
|
|
||||||
|
|
||||||
if (!self)
|
if (!self)
|
||||||
return -1;
|
return -1;
|
||||||
@ -144,9 +118,9 @@ int event_get_url(event_registration_t *er, config_options_t *options) {
|
|||||||
if (strcmp(options->name, "url") == 0) {
|
if (strcmp(options->name, "url") == 0) {
|
||||||
util_replace_string(&(self->url), options->value);
|
util_replace_string(&(self->url), options->value);
|
||||||
} else if (strcmp(options->name, "username") == 0) {
|
} else if (strcmp(options->name, "username") == 0) {
|
||||||
username = options->value;
|
util_replace_string(&(self->username), options->value);
|
||||||
} else if (strcmp(options->name, "password") == 0) {
|
} else if (strcmp(options->name, "password") == 0) {
|
||||||
password = options->value;
|
util_replace_string(&(self->password), options->value);
|
||||||
} else if (strcmp(options->name, "action") == 0) {
|
} else if (strcmp(options->name, "action") == 0) {
|
||||||
util_replace_string(&(self->action), options->value);
|
util_replace_string(&(self->action), options->value);
|
||||||
} else if (strcmp(options->name, "legacy") == 0) {
|
} 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));
|
} while ((options = options->next));
|
||||||
}
|
}
|
||||||
|
|
||||||
self->handle = icecast_curl_new(NULL, NULL);
|
|
||||||
|
|
||||||
/* check if we are in sane state */
|
/* check if we are in sane state */
|
||||||
if (!self->url || !self->handle) {
|
if (!self->url) {
|
||||||
event_url_free(self);
|
event_url_free(self);
|
||||||
return -1;
|
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->state = self;
|
||||||
er->emit = event_url_emit;
|
er->emit = event_url_emit;
|
||||||
er->free = event_url_free;
|
er->free = event_url_free;
|
||||||
|
@ -82,6 +82,7 @@
|
|||||||
#include "yp.h"
|
#include "yp.h"
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
#include "ping.h"
|
||||||
#include "listensocket.h"
|
#include "listensocket.h"
|
||||||
#include "fastevent.h"
|
#include "fastevent.h"
|
||||||
#include "prng.h"
|
#include "prng.h"
|
||||||
@ -169,6 +170,7 @@ static void initialize_subsystems(void)
|
|||||||
xslt_initialize();
|
xslt_initialize();
|
||||||
#ifdef HAVE_CURL
|
#ifdef HAVE_CURL
|
||||||
icecast_curl_initialize();
|
icecast_curl_initialize();
|
||||||
|
ping_initialize();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,6 +184,9 @@ static void shutdown_subsystems(void)
|
|||||||
auth_shutdown();
|
auth_shutdown();
|
||||||
yp_shutdown();
|
yp_shutdown();
|
||||||
stats_shutdown();
|
stats_shutdown();
|
||||||
|
#ifdef HAVE_CURL
|
||||||
|
ping_shutdown();
|
||||||
|
#endif
|
||||||
|
|
||||||
ICECAST_LOG_DEBUG("Shuting down connection related subsystems...");
|
ICECAST_LOG_DEBUG("Shuting down connection related subsystems...");
|
||||||
connection_shutdown();
|
connection_shutdown();
|
||||||
|
161
src/ping.c
Normal file
161
src/ping.c
Normal 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
17
src/ping.h
Normal 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__ */
|
Loading…
Reference in New Issue
Block a user