1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-09-22 04:15:54 -04:00

Merge branch 'epirat-yp-listenurl-fix'

Good work. Thanks to ePirat.
This commit is contained in:
Philipp Schafft 2020-04-30 08:53:57 +00:00
commit 987bdec373
6 changed files with 166 additions and 132 deletions

View File

@ -63,7 +63,6 @@
#define CONFIG_DEFAULT_SHOUTCAST_MOUNT "/stream"
#define CONFIG_DEFAULT_SHOUTCAST_USER "source"
#define CONFIG_DEFAULT_FILESERVE 1
#define CONFIG_DEFAULT_TOUCH_FREQ 5
#define CONFIG_DEFAULT_HOSTNAME "localhost"
#define CONFIG_DEFAULT_PLAYLIST_LOG NULL
#define CONFIG_DEFAULT_ACCESS_LOG "access.log"
@ -161,7 +160,8 @@ static ice_config_locks _locks;
static void _set_defaults(ice_config_t *c);
static void _parse_root(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_limits(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_directory(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_oldstyle_directory(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_yp_directory(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_paths(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_logging(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_security(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
@ -178,7 +178,6 @@ static void _parse_listen_socket(xmlDocPtr doc,
xmlNodePtr node,
ice_config_t *c);
static void _add_server(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_events(event_registration_t **events, xmlNodePtr node);
static void merge_mounts(mount_proxy * dst, mount_proxy * src);
@ -633,6 +632,19 @@ static void config_clear_resource(resource_t *resource)
}
}
static void config_clear_yp_directories(yp_directory_t *yp_dir)
{
yp_directory_t *next_yp_dir;
while (yp_dir) {
next_yp_dir = yp_dir->next;
free(yp_dir->url);
free(yp_dir->listen_socket_id);
free(yp_dir);
yp_dir = next_yp_dir;
}
}
listener_t *config_clear_listener(listener_t *listener)
{
listener_t *next = NULL;
@ -651,8 +663,6 @@ listener_t *config_clear_listener(listener_t *listener)
void config_clear(ice_config_t *c)
{
ice_config_dir_t *dirnode,
*nextdirnode;
mount_proxy *mount,
*nextmount;
size_t i;
@ -708,17 +718,8 @@ void config_clear(ice_config_t *c)
config_clear_resource(c->resources);
dirnode = c->dir_list;
while (dirnode) {
nextdirnode = dirnode->next;
xmlFree(dirnode->host);
free(dirnode);
dirnode = nextdirnode;
}
#ifdef USE_YP
for (i = 0; i < c->num_yp_directories; i++) {
xmlFree(c->yp_url[i]);
}
config_clear_yp_directories(c->yp_directories);
#endif
config_clear_http_header(c->http_headers);
@ -877,12 +878,8 @@ static void _set_defaults(ice_config_t *configuration)
->shoutcast_user = (char *) xmlCharStrdup(CONFIG_DEFAULT_SHOUTCAST_USER);
configuration
->fileserve = CONFIG_DEFAULT_FILESERVE;
configuration
->touch_interval = CONFIG_DEFAULT_TOUCH_FREQ;
configuration
->on_demand = 0;
configuration
->dir_list = NULL;
configuration
->hostname = (char *) xmlCharStrdup(CONFIG_DEFAULT_HOSTNAME);
configuration
@ -923,8 +920,6 @@ static void _set_defaults(ice_config_t *configuration)
->user = NULL;
configuration
->group = NULL;
configuration
->num_yp_directories = 0;
/* default to a typical prebuffer size used by clients */
configuration
->burst_size = CONFIG_DEFAULT_BURST_SIZE;
@ -1094,7 +1089,9 @@ static void _parse_root(xmlDocPtr doc,
} else if (xmlStrcmp(node->name, XMLSTR("mount")) == 0) {
_parse_mount(doc, node, configuration);
} else if (xmlStrcmp(node->name, XMLSTR("directory")) == 0) {
_parse_directory(doc, node->xmlChildrenNode, configuration);
_parse_oldstyle_directory(doc, node->xmlChildrenNode, configuration);
} else if (xmlStrcmp(node->name, XMLSTR("yp-directory")) == 0) {
_parse_yp_directory(doc, node, configuration);
} else if (xmlStrcmp(node->name, XMLSTR("paths")) == 0) {
_parse_paths(doc, node->xmlChildrenNode, configuration);
} else if (xmlStrcmp(node->name, XMLSTR("logging")) == 0) {
@ -2048,14 +2045,19 @@ static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node,
configuration->authstack = old_style;
}
static void _parse_directory(xmlDocPtr doc,
xmlNodePtr node,
ice_config_t *configuration)
static void _parse_oldstyle_directory(xmlDocPtr doc,
xmlNodePtr node,
ice_config_t *configuration)
{
if (configuration->num_yp_directories >= MAX_YP_DIRECTORIES) {
ICECAST_LOG_ERROR("Maximum number of yp directories exceeded!");
yp_directory_t *yp_dir,
*current, *last;
yp_dir = calloc(1, sizeof(*yp_dir));
if (yp_dir == NULL) {
ICECAST_LOG_ERROR("Can not allocate memory for YP directory entry.");
return;
}
do {
if (node == NULL)
break;
@ -2063,21 +2065,93 @@ static void _parse_directory(xmlDocPtr doc,
continue;
if (xmlStrcmp(node->name, XMLSTR("yp-url")) == 0) {
if (configuration->yp_url[configuration->num_yp_directories])
xmlFree(configuration->yp_url[configuration->num_yp_directories]);
configuration->yp_url[configuration->num_yp_directories] =
(char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (yp_dir->url)
xmlFree(yp_dir->url);
yp_dir->url = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (xmlStrcmp(node->name, XMLSTR("yp-url-timeout")) == 0) {
__read_int(doc, node, &configuration->yp_url_timeout[configuration->num_yp_directories], "<yp-url-timeout> must not be empty.");
} else if (xmlStrcmp(node->name, XMLSTR("server")) == 0) {
_add_server(doc, node->xmlChildrenNode, configuration);
__read_int(doc, node, &yp_dir->timeout, "<yp-url-timeout> must not be empty.");
} else if (xmlStrcmp(node->name, XMLSTR("touch-interval")) == 0) {
__read_int(doc, node, &configuration->yp_touch_interval[configuration->num_yp_directories], "<touch-interval> must not be empty.");
__read_int(doc, node, &yp_dir->touch_interval, "<touch-interval> must not be empty.");
}
} while ((node = node->next));
if (configuration->yp_url[configuration->num_yp_directories] == NULL)
if (yp_dir->url == NULL)
return;
configuration->num_yp_directories++;
/* Append YP directory entry to the global list */
current = configuration->yp_directories;
last = NULL;
while (current) {
last = current;
current = current->next;
}
if (last) {
last->next = yp_dir;
} else {
configuration->yp_directories = yp_dir;
}
}
static void _parse_yp_directory(xmlDocPtr doc,
xmlNodePtr node,
ice_config_t *configuration)
{
char *url;
config_options_t *options;
yp_directory_t *yp_dir,
*current, *last;
url = (char *)xmlGetProp(node, XMLSTR("url"));
if (url == NULL) {
ICECAST_LOG_ERROR("Missing mandatory attribute 'url' for <yp-directory>.");
return;
}
yp_dir = calloc(1, sizeof(*yp_dir));
if (yp_dir == NULL) {
ICECAST_LOG_ERROR("Can not allocate memory for YP directory entry.");
return;
}
yp_dir->url = url;
options = config_parse_options(node);
for (config_options_t *opt = options; opt; opt = opt->next) {
if (!opt->name || !opt->value) {
ICECAST_LOG_WARN("Invalid <option>, missing 'name' and 'value' attributes.");
continue;
}
if (strcmp(opt->name, "timeout") == 0) {
yp_dir->timeout = util_str_to_int(opt->value, yp_dir->timeout);
} else if (strcmp(opt->name, "touch-interval") == 0) {
yp_dir->touch_interval = util_str_to_int(opt->value, yp_dir->touch_interval);
} else if (strcmp(opt->name, "listen-socket") == 0) {
if (yp_dir->listen_socket_id) {
ICECAST_LOG_ERROR(
"Multiple 'listen-socket' in <yp-directory> currently unsupported. "
"Only the last one will be used.");
free(yp_dir->listen_socket_id);
}
yp_dir->listen_socket_id = config_href_to_id(opt->value);
} else {
ICECAST_LOG_WARN("Invalid YP <option> with unknown 'name' attribute.");
}
}
config_clear_options(options);
/* Append YP directory entry to the global list */
current = configuration->yp_directories;
last = NULL;
while (current) {
last = current;
current = current->next;
}
if (last) {
last->next = yp_dir;
} else {
configuration->yp_directories = yp_dir;
}
}
static void _parse_resource(xmlDocPtr doc,
@ -2416,51 +2490,6 @@ static void _parse_security(xmlDocPtr doc,
} while ((node = node->next));
}
static void _add_server(xmlDocPtr doc,
xmlNodePtr node,
ice_config_t *configuration)
{
ice_config_dir_t *dirnode,
*server;
int addnode;
server = (ice_config_dir_t *)malloc(sizeof(ice_config_dir_t));
server->touch_interval = configuration->touch_interval;
server->host = NULL;
addnode = 0;
do {
if (node == NULL)
break;
if (xmlIsBlankNode(node))
continue;
if (xmlStrcmp(node->name, XMLSTR("host")) == 0) {
server->host = (char *) xmlNodeListGetString(doc,
node->xmlChildrenNode, 1);
addnode = 1;
} else if (xmlStrcmp(node->name, XMLSTR("touch-interval")) == 0) {
__read_int(doc, node, &server->touch_interval, "<touch-interval> must not be empty.");
}
server->next = NULL;
} while ((node = node->next));
if (addnode) {
dirnode = configuration->dir_list;
if (dirnode == NULL) {
configuration->dir_list = server;
} else {
while (dirnode->next) dirnode = dirnode->next;
dirnode->next = server;
}
server = NULL;
addnode = 0;
} else {
free (server);
}
}
static void _parse_events(event_registration_t **events, xmlNodePtr node)
{
while (node) {

View File

@ -20,8 +20,6 @@
#define CONFIG_EBADROOT -3
#define CONFIG_EPARSE -4
#define MAX_YP_DIRECTORIES 25
#include <libxml/tree.h>
#include "common/thread/thread.h"
#include "common/avl/avl.h"
@ -52,12 +50,6 @@ typedef struct ice_config_http_header_tag {
struct ice_config_http_header_tag *next;
} ice_config_http_header_t;
typedef struct ice_config_dir_tag {
char *host;
int touch_interval;
struct ice_config_dir_tag *next;
} ice_config_dir_t;
struct _config_options {
char *type;
char *name;
@ -150,6 +142,14 @@ typedef struct _resource {
struct _resource *next;
} resource_t;
typedef struct _yp_directory {
char *url;
int timeout;
int touch_interval;
char *listen_socket_id;
struct _yp_directory *next;
} yp_directory_t;
typedef enum _listener_type_tag {
LISTENER_TYPE_ERROR,
LISTENER_TYPE_NORMAL,
@ -219,9 +219,6 @@ struct ice_config_tag {
struct event_registration_tag *event;
int touch_interval;
ice_config_dir_t *dir_list;
char *hostname;
int sane_hostname;
int port;
@ -271,10 +268,8 @@ struct ice_config_tag {
int chuid;
char *user;
char *group;
char *yp_url[MAX_YP_DIRECTORIES];
int yp_url_timeout[MAX_YP_DIRECTORIES];
int yp_touch_interval[MAX_YP_DIRECTORIES];
size_t num_yp_directories;
yp_directory_t *yp_directories;
};
typedef struct {

View File

@ -39,8 +39,6 @@ int main(void)
void _dump_config(ice_config_t *config)
{
ice_config_dir_t *node;
printf("-----\n");
printf("location = %s\n", config->location);
printf("admin = %s\n", config->admin);
@ -49,16 +47,6 @@ void _dump_config(ice_config_t *config)
printf("threadpool_size = %d\n", config->threadpool_size);
printf("client_timeout = %d\n", config->client_timeout);
printf("source_password = %s\n", config->source_password);
printf("touch_interval = %d\n", config->touch_interval);
node = config->dir_list;
while (node) {
printf("directory.touch_interval = %d\n", node->touch_interval);
printf("directory.host = %s\n", node->host);
node = node->next;
}
printf("hostname = %s\n", config->hostname);
printf("port = %d\n", config->port);
printf("bind_address = %s\n", config->bind_address);

View File

@ -53,7 +53,6 @@ struct listensocket_tag {
sock_t sock;
};
static listensocket_t * listensocket_container_get_by_id(listensocket_container_t *self, const char *id);
static int listensocket_container_configure__unlocked(listensocket_container_t *self, const ice_config_t *config);
static int listensocket_container_setup__unlocked(listensocket_container_t *self);
static ssize_t listensocket_container_sockcount__unlocked(listensocket_container_t *self);
@ -484,7 +483,7 @@ static ssize_t listensocket_container_sockcount__unlocked(listensocket_container
return count;
}
static listensocket_t * listensocket_container_get_by_id(listensocket_container_t *self, const char *id)
listensocket_t * listensocket_container_get_by_id(listensocket_container_t *self, const char *id)
{
size_t i;
const listener_t *listener;

View File

@ -22,6 +22,7 @@ int listensocket_container_setup(listensocket_container_
connection_t * listensocket_container_accept(listensocket_container_t *self, int timeout);
int listensocket_container_set_sockcount_cb(listensocket_container_t *self, void (*cb)(size_t count, void *userdata), void *userdata);
ssize_t listensocket_container_sockcount(listensocket_container_t *self);
listensocket_t * listensocket_container_get_by_id(listensocket_container_t *self, const char *id);
REFOBJECT_FORWARD_TYPE(listensocket_t);

View File

@ -29,6 +29,7 @@
#include "source.h"
#include "cfgfile.h"
#include "stats.h"
#include "listensocket.h"
#ifdef WIN32
#define snprintf _snprintf
@ -43,6 +44,7 @@ struct yp_server
unsigned url_timeout;
unsigned touch_interval;
int remove;
char *listen_socket_id;
CURL *curl;
struct ypdata_tag *mounts, *pending_mounts;
@ -217,7 +219,6 @@ static ypdata_t *find_yp_mount (ypdata_t *mounts, const char *mount)
void yp_recheck_config (ice_config_t *config)
{
size_t i;
struct yp_server *server;
ICECAST_LOG_DEBUG("Updating YP configuration");
@ -234,9 +235,9 @@ void yp_recheck_config (ice_config_t *config)
server_version = strdup (config->server_id);
/* for each yp url in config, check to see if one exists
if not, then add it. */
for (i=0 ; i < config->num_yp_directories; i++)
for (yp_directory_t *yp = config->yp_directories; yp; yp = yp->next)
{
server = find_yp_server (config->yp_url[i]);
server = find_yp_server (yp->url);
if (server == NULL)
{
server = calloc (1, sizeof (struct yp_server));
@ -247,9 +248,10 @@ void yp_recheck_config (ice_config_t *config)
break;
}
server->server_id = strdup ((char *)server_version);
server->url = strdup (config->yp_url[i]);
server->url_timeout = config->yp_url_timeout[i];
server->touch_interval = config->yp_touch_interval[i];
server->url = strdup (yp->url);
server->url_timeout = yp->timeout;
server->touch_interval = yp->touch_interval;
server->listen_socket_id = yp->listen_socket_id;
server->curl = icecast_curl_new(server->url, &(server->curl_error[0]));
if (server->curl == NULL)
{
@ -563,16 +565,19 @@ static void yp_process_server (struct yp_server *server)
static ypdata_t *create_yp_entry (const char *mount)
static ypdata_t *create_yp_entry (struct yp_server *server, const char *mount)
{
ypdata_t *yp;
char *s;
if (!server)
return NULL;
yp = calloc (1, sizeof (ypdata_t));
do
{
listensocket_t *listen_socket = NULL;
unsigned len = 512;
int ret;
ssize_t ret;
char *url;
mount_proxy *mountproxy = NULL;
ice_config_t *config;
@ -595,15 +600,33 @@ static ypdata_t *create_yp_entry (const char *mount)
url = malloc (len);
if (url == NULL)
break;
config = config_get_config();
ret = snprintf (url, len, "http://%s:%d%s", config->hostname, config->port, mount);
if (ret >= (signed)len)
{
s = realloc (url, ++ret);
if (s) url = s;
snprintf (url, ret, "http://%s:%d%s", config->hostname, config->port, mount);
}
if (server->listen_socket_id) {
listen_socket = listensocket_container_get_by_id(global.listensockets,
server->listen_socket_id);
if (!listen_socket)
ICECAST_LOG_ERROR("Failure to find listen socket with ID %#H, using default.",
server->listen_socket_id);
}
ret = client_get_baseurl(NULL, listen_socket, url, len, NULL, NULL, NULL, mount, NULL);
if (ret >= len) {
// Buffer was too small, allocate a big enough one
char *s = realloc (url, ret + 1);
if (!s) {
refobject_unref(listen_socket);
free(url);
break;
}
url = s;
ret = client_get_baseurl(NULL, listen_socket, url, len, NULL, NULL, NULL, mount, NULL);
}
refobject_unref(listen_socket);
if (ret < 0 || ret >= len)
break;
config = config_get_config();
mountproxy = config_find_mount (config, mount, MOUNT_TYPE_NORMAL);
if (mountproxy && mountproxy->cluster_password)
add_yp_info (yp, mountproxy->cluster_password, YP_CLUSTER_PASSWORD);
@ -633,7 +656,7 @@ static void check_servers (void)
if (server->remove)
{
struct yp_server *to_go = server;
ICECAST_LOG_DEBUG("YP server \"%s\"removed", server->url);
ICECAST_LOG_DEBUG("YP server \"%s\" removed", server->url);
*server_p = server->next;
server = server->next;
destroy_yp_server(to_go);
@ -662,10 +685,9 @@ static void check_servers (void)
ypdata_t *yp;
source_t *source = node->key;
if (source->yp_public && (yp = create_yp_entry (source->mount)) != NULL)
if (source->yp_public && (yp = create_yp_entry (server, source->mount)) != NULL)
{
ICECAST_LOG_DEBUG("Adding existing mount %s", source->mount);
yp->server = server;
yp->touch_interval = server->touch_interval;
yp->next = server->mounts;
server->mounts = yp;
@ -901,7 +923,7 @@ void yp_add (const char *mount)
if (yp == NULL)
{
/* add new ypdata to each servers pending yp */
yp = create_yp_entry (mount);
yp = create_yp_entry (server, mount);
if (yp)
{
ICECAST_LOG_DEBUG("Adding %s to %s", mount, server->url);