1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-12-04 14:46:30 -05:00

Allow rereading config files.

Lots of new locking happening so that it's safe to have the config file
disappear under the rest of the program

Does NOT affect currently-running sources at the moment

svn path=/trunk/icecast/; revision=4406
This commit is contained in:
Michael Smith 2003-03-05 13:03:35 +00:00
parent 4c08a155c7
commit d13ebde7a3
17 changed files with 544 additions and 243 deletions

View File

@ -1,5 +1,7 @@
(Note: from here on, the changelog generally only includes new features, not
bug fixes)
2003-03-05
Implemented the ability to reread the config file on SIGHUP. For now, this
does not affect configuration for currently running sources (only new
sources and global parameters like max-listeners)
2003-03-02
More features:

6
TODO
View File

@ -50,6 +50,8 @@ FEATURES
- option to use ipv6 (equiv to using <bind-address>::</bindaddress>, I think.
- per-mountpoint listener maximums.
- abstract all admin functionality to a set of commands, and command handlers.
Make /admin/* just parse according to a set of rules, and dispatch generic
commands through that.
Use this for alternative admin interfaces (GUI? telnet interface?)

View File

@ -8,10 +8,10 @@ bin_PROGRAMS = icecast
noinst_HEADERS = config.h os.h logging.h sighandler.h connection.h global.h\
util.h slave.h source.h stats.h refbuf.h client.h format.h format_vorbis.h\
compat.h format_mp3.h fserve.h xslt.h geturl.h yp.h
compat.h format_mp3.h fserve.h xslt.h geturl.h yp.h event.h
icecast_SOURCES = config.c main.c logging.c sighandler.c connection.c global.c\
util.c slave.c source.c stats.c refbuf.c client.c format.c format_vorbis.c\
format_mp3.c xslt.c fserve.c geturl.c yp.c
format_mp3.c xslt.c fserve.c geturl.c yp.c event.c
icecast_LDADD = net/libicenet.la thread/libicethread.la httpp/libicehttpp.la\
log/libicelog.la avl/libiceavl.la timing/libicetiming.la

View File

@ -3,6 +3,8 @@
#include <string.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include "thread/thread.h"
#include "config.h"
#include "refbuf.h"
#include "client.h"
@ -45,36 +47,59 @@
#define CONFIG_DEFAULT_WEBROOT_DIR ".\\webroot"
#endif
ice_config_t _configuration;
char *_config_filename;
ice_config_t _current_configuration;
ice_config_locks _locks;
static void _set_defaults(void);
static void _parse_root(xmlDocPtr doc, xmlNodePtr node);
static void _parse_limits(xmlDocPtr doc, xmlNodePtr node);
static void _parse_directory(xmlDocPtr doc, xmlNodePtr node);
static void _parse_paths(xmlDocPtr doc, xmlNodePtr node);
static void _parse_logging(xmlDocPtr doc, xmlNodePtr node);
static void _parse_security(xmlDocPtr doc, xmlNodePtr node);
static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node);
static void _parse_relay(xmlDocPtr doc, xmlNodePtr node);
static void _parse_mount(xmlDocPtr doc, xmlNodePtr node);
static void _add_server(xmlDocPtr doc, xmlNodePtr node);
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_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);
static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *c);
static void _parse_relay(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_mount(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _add_server(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
void config_initialize(void)
{
memset(&_configuration, 0, sizeof(ice_config_t));
_set_defaults();
_config_filename = NULL;
static void create_locks() {
thread_mutex_create(&_locks.relay_lock);
thread_mutex_create(&_locks.mounts_lock);
thread_mutex_create(&_locks.config_lock);
}
void config_shutdown(void)
static void release_locks() {
thread_mutex_destroy(&_locks.relay_lock);
thread_mutex_destroy(&_locks.mounts_lock);
thread_mutex_destroy(&_locks.config_lock);
}
void config_initialize(void) {
create_locks();
}
void config_shutdown(void) {
config_get_config();
config_clear(&_current_configuration);
config_release_config();
release_locks();
}
void config_init_configuration(ice_config_t *configuration)
{
memset(configuration, 0, sizeof(ice_config_t));
_set_defaults(configuration);
}
void config_clear(ice_config_t *c)
{
ice_config_dir_t *dirnode, *nextdirnode;
ice_config_t *c = &_configuration;
relay_server *relay, *nextrelay;
mount_proxy *mount, *nextmount;
if (_config_filename) free(_config_filename);
if (c->config_filename)
free(c->config_filename);
if (c->location && c->location != CONFIG_DEFAULT_LOCATION)
xmlFree(c->location);
@ -105,7 +130,9 @@ void config_shutdown(void)
if (c->master_password) xmlFree(c->master_password);
if (c->user) xmlFree(c->user);
if (c->group) xmlFree(c->group);
relay = _configuration.relay;
thread_mutex_lock(&(_locks.relay_lock));
relay = c->relay;
while(relay) {
nextrelay = relay->next;
xmlFree(relay->server);
@ -115,7 +142,10 @@ void config_shutdown(void)
free(relay);
relay = nextrelay;
}
mount = _configuration.mounts;
thread_mutex_unlock(&(_locks.relay_lock));
thread_mutex_lock(&(_locks.mounts_lock));
mount = c->mounts;
while(mount) {
nextmount = mount->next;
xmlFree(mount->mountname);
@ -126,7 +156,9 @@ void config_shutdown(void)
free(mount);
mount = nextmount;
}
dirnode = _configuration.dir_list;
thread_mutex_unlock(&(_locks.mounts_lock));
dirnode = c->dir_list;
while(dirnode) {
nextdirnode = dirnode->next;
xmlFree(dirnode->host);
@ -137,17 +169,21 @@ void config_shutdown(void)
memset(c, 0, sizeof(ice_config_t));
}
int config_parse_file(const char *filename)
int config_initial_parse_file(const char *filename)
{
/* Since we're already pointing at it, we don't need to copy it in place */
return config_parse_file(filename, &_current_configuration);
}
int config_parse_file(const char *filename, ice_config_t *configuration)
{
xmlDocPtr doc;
xmlNodePtr node;
if (filename == NULL || strcmp(filename, "") == 0) return CONFIG_EINSANE;
_config_filename = (char *)strdup(filename);
xmlInitParser();
doc = xmlParseFile(_config_filename);
doc = xmlParseFile(filename);
if (doc == NULL) {
return CONFIG_EPARSE;
}
@ -165,7 +201,11 @@ int config_parse_file(const char *filename)
return CONFIG_EBADROOT;
}
_parse_root(doc, node->xmlChildrenNode);
config_init_configuration(configuration);
configuration->config_filename = (char *)strdup(filename);
_parse_root(doc, node->xmlChildrenNode, configuration);
xmlFreeDoc(doc);
xmlCleanupParser();
@ -178,54 +218,71 @@ int config_parse_cmdline(int arg, char **argv)
return 0;
}
int config_rehash(void)
ice_config_locks *config_locks(void)
{
return 0;
return &_locks;
}
void config_release_config(void)
{
thread_mutex_unlock(&(_locks.config_lock));
}
ice_config_t *config_get_config(void)
{
return &_configuration;
thread_mutex_lock(&(_locks.config_lock));
return &_current_configuration;
}
static void _set_defaults(void)
/* MUST be called with the lock held! */
void config_set_config(ice_config_t *config) {
memcpy(&_current_configuration, config, sizeof(ice_config_t));
}
ice_config_t *config_get_config_unlocked(void)
{
_configuration.location = CONFIG_DEFAULT_LOCATION;
_configuration.admin = CONFIG_DEFAULT_ADMIN;
_configuration.client_limit = CONFIG_DEFAULT_CLIENT_LIMIT;
_configuration.source_limit = CONFIG_DEFAULT_SOURCE_LIMIT;
_configuration.queue_size_limit = CONFIG_DEFAULT_QUEUE_SIZE_LIMIT;
_configuration.threadpool_size = CONFIG_DEFAULT_THREADPOOL_SIZE;
_configuration.client_timeout = CONFIG_DEFAULT_CLIENT_TIMEOUT;
_configuration.header_timeout = CONFIG_DEFAULT_HEADER_TIMEOUT;
_configuration.source_timeout = CONFIG_DEFAULT_SOURCE_TIMEOUT;
_configuration.source_password = CONFIG_DEFAULT_SOURCE_PASSWORD;
_configuration.relay_password = CONFIG_DEFAULT_RELAY_PASSWORD;
_configuration.ice_login = CONFIG_DEFAULT_ICE_LOGIN;
_configuration.fileserve = CONFIG_DEFAULT_FILESERVE;
_configuration.touch_interval = CONFIG_DEFAULT_TOUCH_FREQ;
_configuration.dir_list = NULL;
_configuration.hostname = CONFIG_DEFAULT_HOSTNAME;
_configuration.port = CONFIG_DEFAULT_PORT;
_configuration.bind_address = NULL;
_configuration.master_server = NULL;
_configuration.master_server_port = CONFIG_DEFAULT_PORT;
_configuration.master_update_interval = CONFIG_MASTER_UPDATE_INTERVAL;
_configuration.master_password = NULL;
_configuration.base_dir = CONFIG_DEFAULT_BASE_DIR;
_configuration.log_dir = CONFIG_DEFAULT_LOG_DIR;
_configuration.webroot_dir = CONFIG_DEFAULT_WEBROOT_DIR;
_configuration.access_log = CONFIG_DEFAULT_ACCESS_LOG;
_configuration.error_log = CONFIG_DEFAULT_ERROR_LOG;
_configuration.loglevel = CONFIG_DEFAULT_LOG_LEVEL;
_configuration.chroot = CONFIG_DEFAULT_CHROOT;
_configuration.chuid = CONFIG_DEFAULT_CHUID;
_configuration.user = CONFIG_DEFAULT_USER;
_configuration.group = CONFIG_DEFAULT_GROUP;
_configuration.num_yp_directories = 0;
return &_current_configuration;
}
static void _parse_root(xmlDocPtr doc, xmlNodePtr node)
static void _set_defaults(ice_config_t *configuration)
{
configuration->location = CONFIG_DEFAULT_LOCATION;
configuration->admin = CONFIG_DEFAULT_ADMIN;
configuration->client_limit = CONFIG_DEFAULT_CLIENT_LIMIT;
configuration->source_limit = CONFIG_DEFAULT_SOURCE_LIMIT;
configuration->queue_size_limit = CONFIG_DEFAULT_QUEUE_SIZE_LIMIT;
configuration->threadpool_size = CONFIG_DEFAULT_THREADPOOL_SIZE;
configuration->client_timeout = CONFIG_DEFAULT_CLIENT_TIMEOUT;
configuration->header_timeout = CONFIG_DEFAULT_HEADER_TIMEOUT;
configuration->source_timeout = CONFIG_DEFAULT_SOURCE_TIMEOUT;
configuration->source_password = CONFIG_DEFAULT_SOURCE_PASSWORD;
configuration->relay_password = CONFIG_DEFAULT_RELAY_PASSWORD;
configuration->ice_login = CONFIG_DEFAULT_ICE_LOGIN;
configuration->fileserve = CONFIG_DEFAULT_FILESERVE;
configuration->touch_interval = CONFIG_DEFAULT_TOUCH_FREQ;
configuration->dir_list = NULL;
configuration->hostname = CONFIG_DEFAULT_HOSTNAME;
configuration->port = CONFIG_DEFAULT_PORT;
configuration->bind_address = NULL;
configuration->master_server = NULL;
configuration->master_server_port = CONFIG_DEFAULT_PORT;
configuration->master_update_interval = CONFIG_MASTER_UPDATE_INTERVAL;
configuration->master_password = NULL;
configuration->base_dir = CONFIG_DEFAULT_BASE_DIR;
configuration->log_dir = CONFIG_DEFAULT_LOG_DIR;
configuration->webroot_dir = CONFIG_DEFAULT_WEBROOT_DIR;
configuration->access_log = CONFIG_DEFAULT_ACCESS_LOG;
configuration->error_log = CONFIG_DEFAULT_ERROR_LOG;
configuration->loglevel = CONFIG_DEFAULT_LOG_LEVEL;
configuration->chroot = CONFIG_DEFAULT_CHROOT;
configuration->chuid = CONFIG_DEFAULT_CHUID;
configuration->user = CONFIG_DEFAULT_USER;
configuration->group = CONFIG_DEFAULT_GROUP;
configuration->num_yp_directories = 0;
}
static void _parse_root(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *configuration)
{
char *tmp;
@ -234,13 +291,13 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node)
if (xmlIsBlankNode(node)) continue;
if (strcmp(node->name, "location") == 0) {
if (_configuration.location && _configuration.location != CONFIG_DEFAULT_LOCATION) xmlFree(_configuration.location);
_configuration.location = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (configuration->location && configuration->location != CONFIG_DEFAULT_LOCATION) xmlFree(configuration->location);
configuration->location = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "admin") == 0) {
if (_configuration.admin && _configuration.admin != CONFIG_DEFAULT_ADMIN) xmlFree(_configuration.admin);
_configuration.admin = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (configuration->admin && configuration->admin != CONFIG_DEFAULT_ADMIN) xmlFree(configuration->admin);
configuration->admin = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if(strcmp(node->name, "authentication") == 0) {
_parse_authentication(doc, node->xmlChildrenNode);
_parse_authentication(doc, node->xmlChildrenNode, configuration);
} else if (strcmp(node->name, "source-password") == 0) {
/* TODO: This is the backwards-compatibility location */
char *mount, *pass;
@ -249,62 +306,63 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node)
/* FIXME: This is a placeholder for per-mount passwords */
}
else {
if (_configuration.source_password && _configuration.source_password != CONFIG_DEFAULT_SOURCE_PASSWORD) xmlFree(_configuration.source_password);
_configuration.source_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (configuration->source_password && configuration->source_password != CONFIG_DEFAULT_SOURCE_PASSWORD) xmlFree(configuration->source_password);
configuration->source_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
}
} else if (strcmp(node->name, "relay-password") == 0) {
/* TODO: This is the backwards-compatibility location */
if (_configuration.relay_password && _configuration.relay_password != CONFIG_DEFAULT_RELAY_PASSWORD) xmlFree(_configuration.relay_password);
_configuration.relay_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (configuration->relay_password && configuration->relay_password != CONFIG_DEFAULT_RELAY_PASSWORD) xmlFree(configuration->relay_password);
configuration->relay_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "icelogin") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.ice_login = atoi(tmp);
configuration->ice_login = atoi(tmp);
if (tmp) xmlFree(tmp);
} else if (strcmp(node->name, "fileserve") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.fileserve = atoi(tmp);
configuration->fileserve = atoi(tmp);
if (tmp) xmlFree(tmp);
} else if (strcmp(node->name, "hostname") == 0) {
if (_configuration.hostname && _configuration.hostname != CONFIG_DEFAULT_HOSTNAME) xmlFree(_configuration.hostname);
_configuration.hostname = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (configuration->hostname && configuration->hostname != CONFIG_DEFAULT_HOSTNAME) xmlFree(configuration->hostname);
configuration->hostname = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "port") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.port = atoi(tmp);
configuration->port = atoi(tmp);
if (tmp) xmlFree(tmp);
} else if (strcmp(node->name, "bind-address") == 0) {
if (_configuration.bind_address) xmlFree(_configuration.bind_address);
_configuration.bind_address = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (configuration->bind_address) xmlFree(configuration->bind_address);
configuration->bind_address = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "master-server") == 0) {
if (_configuration.master_server) xmlFree(_configuration.master_server);
_configuration.master_server = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (configuration->master_server) xmlFree(configuration->master_server);
configuration->master_server = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "master-password") == 0) {
if (_configuration.master_password) xmlFree(_configuration.master_password);
_configuration.master_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (configuration->master_password) xmlFree(configuration->master_password);
configuration->master_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "master-server-port") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.master_server_port = atoi(tmp);
configuration->master_server_port = atoi(tmp);
} else if (strcmp(node->name, "master-update-interval") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.master_update_interval = atoi(tmp);
configuration->master_update_interval = atoi(tmp);
} else if (strcmp(node->name, "limits") == 0) {
_parse_limits(doc, node->xmlChildrenNode);
_parse_limits(doc, node->xmlChildrenNode, configuration);
} else if (strcmp(node->name, "relay") == 0) {
_parse_relay(doc, node->xmlChildrenNode);
_parse_relay(doc, node->xmlChildrenNode, configuration);
} else if (strcmp(node->name, "mount") == 0) {
_parse_mount(doc, node->xmlChildrenNode);
_parse_mount(doc, node->xmlChildrenNode, configuration);
} else if (strcmp(node->name, "directory") == 0) {
_parse_directory(doc, node->xmlChildrenNode);
_parse_directory(doc, node->xmlChildrenNode, configuration);
} else if (strcmp(node->name, "paths") == 0) {
_parse_paths(doc, node->xmlChildrenNode);
_parse_paths(doc, node->xmlChildrenNode, configuration);
} else if (strcmp(node->name, "logging") == 0) {
_parse_logging(doc, node->xmlChildrenNode);
_parse_logging(doc, node->xmlChildrenNode, configuration);
} else if (strcmp(node->name, "security") == 0) {
_parse_security(doc, node->xmlChildrenNode);
_parse_security(doc, node->xmlChildrenNode, configuration);
}
} while ((node = node->next));
}
static void _parse_limits(xmlDocPtr doc, xmlNodePtr node)
static void _parse_limits(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *configuration)
{
char *tmp;
@ -314,41 +372,42 @@ static void _parse_limits(xmlDocPtr doc, xmlNodePtr node)
if (strcmp(node->name, "clients") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.client_limit = atoi(tmp);
configuration->client_limit = atoi(tmp);
if (tmp) xmlFree(tmp);
} else if (strcmp(node->name, "sources") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.source_limit = atoi(tmp);
configuration->source_limit = atoi(tmp);
if (tmp) xmlFree(tmp);
} else if (strcmp(node->name, "queue-size") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.queue_size_limit = atoi(tmp);
configuration->queue_size_limit = atoi(tmp);
if (tmp) xmlFree(tmp);
} else if (strcmp(node->name, "threadpool") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.threadpool_size = atoi(tmp);
configuration->threadpool_size = atoi(tmp);
if (tmp) xmlFree(tmp);
} else if (strcmp(node->name, "client-timeout") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.client_timeout = atoi(tmp);
configuration->client_timeout = atoi(tmp);
if (tmp) xmlFree(tmp);
} else if (strcmp(node->name, "header-timeout") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.header_timeout = atoi(tmp);
configuration->header_timeout = atoi(tmp);
if (tmp) xmlFree(tmp);
} else if (strcmp(node->name, "source-timeout") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.source_timeout = atoi(tmp);
configuration->source_timeout = atoi(tmp);
if (tmp) xmlFree(tmp);
}
} while ((node = node->next));
}
static void _parse_mount(xmlDocPtr doc, xmlNodePtr node)
static void _parse_mount(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *configuration)
{
char *tmp;
mount_proxy *mount = calloc(1, sizeof(mount_proxy));
mount_proxy *current = _configuration.mounts;
mount_proxy *current = configuration->mounts;
mount_proxy *last=NULL;
while(current) {
@ -359,7 +418,7 @@ static void _parse_mount(xmlDocPtr doc, xmlNodePtr node)
if(last)
last->next = mount;
else
_configuration.mounts = mount;
configuration->mounts = mount;
mount->max_listeners = -1;
@ -395,11 +454,12 @@ static void _parse_mount(xmlDocPtr doc, xmlNodePtr node)
} while ((node = node->next));
}
static void _parse_relay(xmlDocPtr doc, xmlNodePtr node)
static void _parse_relay(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *configuration)
{
char *tmp;
relay_server *relay = calloc(1, sizeof(relay_server));
relay_server *current = _configuration.relay;
relay_server *current = configuration->relay;
relay_server *last=NULL;
while(current) {
@ -410,7 +470,7 @@ static void _parse_relay(xmlDocPtr doc, xmlNodePtr node)
if(last)
last->next = relay;
else
_configuration.relay = relay;
configuration->relay = relay;
do {
if (node == NULL) break;
@ -441,7 +501,8 @@ static void _parse_relay(xmlDocPtr doc, xmlNodePtr node)
} while ((node = node->next));
}
static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node)
static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *configuration)
{
do {
if (node == NULL) break;
@ -454,39 +515,40 @@ static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node)
/* FIXME: This is a placeholder for per-mount passwords */
}
else {
if (_configuration.source_password &&
_configuration.source_password !=
if (configuration->source_password &&
configuration->source_password !=
CONFIG_DEFAULT_SOURCE_PASSWORD)
xmlFree(_configuration.source_password);
_configuration.source_password =
xmlFree(configuration->source_password);
configuration->source_password =
(char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
}
} else if (strcmp(node->name, "relay-password") == 0) {
if (_configuration.relay_password &&
_configuration.relay_password !=
if (configuration->relay_password &&
configuration->relay_password !=
CONFIG_DEFAULT_RELAY_PASSWORD)
xmlFree(_configuration.relay_password);
_configuration.relay_password =
xmlFree(configuration->relay_password);
configuration->relay_password =
(char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "admin-password") == 0) {
if(_configuration.admin_password)
xmlFree(_configuration.admin_password);
_configuration.admin_password =
if(configuration->admin_password)
xmlFree(configuration->admin_password);
configuration->admin_password =
(char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "admin-user") == 0) {
if(_configuration.admin_username)
xmlFree(_configuration.admin_username);
_configuration.admin_username =
if(configuration->admin_username)
xmlFree(configuration->admin_username);
configuration->admin_username =
(char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
}
} while ((node = node->next));
}
static void _parse_directory(xmlDocPtr doc, xmlNodePtr node)
static void _parse_directory(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *configuration)
{
char *tmp;
if (_configuration.num_yp_directories >= MAX_YP_DIRECTORIES) {
if (configuration->num_yp_directories >= MAX_YP_DIRECTORIES) {
ERROR0("Maximum number of yp directories exceeded!");
return;
}
@ -495,68 +557,71 @@ static void _parse_directory(xmlDocPtr doc, xmlNodePtr node)
if (xmlIsBlankNode(node)) continue;
if (strcmp(node->name, "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] =
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);
} else if (strcmp(node->name, "yp-url-timeout") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.yp_url_timeout[_configuration.num_yp_directories] =
configuration->yp_url_timeout[configuration->num_yp_directories] =
atoi(tmp);
} else if (strcmp(node->name, "server") == 0) {
_add_server(doc, node->xmlChildrenNode);
_add_server(doc, node->xmlChildrenNode, configuration);
} else if (strcmp(node->name, "touch-interval") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.touch_interval = atoi(tmp);
configuration->touch_interval = atoi(tmp);
if (tmp) xmlFree(tmp);
}
} while ((node = node->next));
_configuration.num_yp_directories++;
configuration->num_yp_directories++;
}
static void _parse_paths(xmlDocPtr doc, xmlNodePtr node)
static void _parse_paths(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *configuration)
{
do {
if (node == NULL) break;
if (xmlIsBlankNode(node)) continue;
if (strcmp(node->name, "basedir") == 0) {
if (_configuration.base_dir && _configuration.base_dir != CONFIG_DEFAULT_BASE_DIR) xmlFree(_configuration.base_dir);
_configuration.base_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (configuration->base_dir && configuration->base_dir != CONFIG_DEFAULT_BASE_DIR) xmlFree(configuration->base_dir);
configuration->base_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "logdir") == 0) {
if (_configuration.log_dir && _configuration.log_dir != CONFIG_DEFAULT_LOG_DIR) xmlFree(_configuration.log_dir);
_configuration.log_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (configuration->log_dir && configuration->log_dir != CONFIG_DEFAULT_LOG_DIR) xmlFree(configuration->log_dir);
configuration->log_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "webroot") == 0) {
if (_configuration.webroot_dir && _configuration.webroot_dir != CONFIG_DEFAULT_WEBROOT_DIR) xmlFree(_configuration.webroot_dir);
_configuration.webroot_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if(_configuration.webroot_dir[strlen(_configuration.webroot_dir)-1] == '/')
_configuration.webroot_dir[strlen(_configuration.webroot_dir)-1] = 0;
if (configuration->webroot_dir && configuration->webroot_dir != CONFIG_DEFAULT_WEBROOT_DIR) xmlFree(configuration->webroot_dir);
configuration->webroot_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if(configuration->webroot_dir[strlen(configuration->webroot_dir)-1] == '/')
configuration->webroot_dir[strlen(configuration->webroot_dir)-1] = 0;
}
} while ((node = node->next));
}
static void _parse_logging(xmlDocPtr doc, xmlNodePtr node)
static void _parse_logging(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *configuration)
{
do {
if (node == NULL) break;
if (xmlIsBlankNode(node)) continue;
if (strcmp(node->name, "accesslog") == 0) {
if (_configuration.access_log && _configuration.access_log != CONFIG_DEFAULT_ACCESS_LOG) xmlFree(_configuration.access_log);
_configuration.access_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (configuration->access_log && configuration->access_log != CONFIG_DEFAULT_ACCESS_LOG) xmlFree(configuration->access_log);
configuration->access_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "errorlog") == 0) {
if (_configuration.error_log && _configuration.error_log != CONFIG_DEFAULT_ERROR_LOG) xmlFree(_configuration.error_log);
_configuration.error_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (configuration->error_log && configuration->error_log != CONFIG_DEFAULT_ERROR_LOG) xmlFree(configuration->error_log);
configuration->error_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "loglevel") == 0) {
char *tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.loglevel = atoi(tmp);
configuration->loglevel = atoi(tmp);
if (tmp) xmlFree(tmp);
}
} while ((node = node->next));
}
static void _parse_security(xmlDocPtr doc, xmlNodePtr node)
static void _parse_security(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *configuration)
{
char *tmp;
xmlNodePtr oldnode;
@ -567,21 +632,21 @@ static void _parse_security(xmlDocPtr doc, xmlNodePtr node)
if (strcmp(node->name, "chroot") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.chroot = atoi(tmp);
configuration->chroot = atoi(tmp);
if (tmp) xmlFree(tmp);
} else if (strcmp(node->name, "changeowner") == 0) {
_configuration.chuid = 1;
configuration->chuid = 1;
oldnode = node;
node = node->xmlChildrenNode;
do {
if(node == NULL) break;
if(xmlIsBlankNode(node)) continue;
if(strcmp(node->name, "user") == 0) {
if(_configuration.user) xmlFree(_configuration.user);
_configuration.user = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if(configuration->user) xmlFree(configuration->user);
configuration->user = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if(strcmp(node->name, "group") == 0) {
if(_configuration.group) xmlFree(_configuration.group);
_configuration.group = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if(configuration->group) xmlFree(configuration->group);
configuration->group = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
}
} while((node = node->next));
node = oldnode;
@ -589,14 +654,15 @@ static void _parse_security(xmlDocPtr doc, xmlNodePtr node)
} while ((node = node->next));
}
static void _add_server(xmlDocPtr doc, xmlNodePtr node)
static void _add_server(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *configuration)
{
ice_config_dir_t *dirnode, *server;
int addnode;
char *tmp;
server = (ice_config_dir_t *)malloc(sizeof(ice_config_dir_t));
server->touch_interval = _configuration.touch_interval;
server->touch_interval = configuration->touch_interval;
server->host = NULL;
addnode = 0;
@ -617,9 +683,9 @@ static void _add_server(xmlDocPtr doc, xmlNodePtr node)
} while ((node = node->next));
if (addnode) {
dirnode = _configuration.dir_list;
dirnode = configuration->dir_list;
if (dirnode == NULL) {
_configuration.dir_list = server;
configuration->dir_list = server;
} else {
while (dirnode->next) dirnode = dirnode->next;

View File

@ -8,6 +8,8 @@
#define MAX_YP_DIRECTORIES 25
#include "thread/thread.h"
typedef struct ice_config_dir_tag
{
char *host;
@ -40,6 +42,8 @@ typedef struct _mount_proxy {
typedef struct ice_config_tag
{
char *config_filename;
char *location;
char *admin;
@ -90,15 +94,30 @@ typedef struct ice_config_tag
int num_yp_directories;
} ice_config_t;
typedef struct {
mutex_t config_lock;
mutex_t relay_lock;
mutex_t mounts_lock;
} ice_config_locks;
void config_initialize(void);
void config_shutdown(void);
int config_parse_file(const char *filename);
int config_parse_file(const char *filename, ice_config_t *configuration);
int config_initial_parse_file(const char *filename);
int config_parse_cmdline(int arg, char **argv);
void config_set_config(ice_config_t *config);
void config_clear(ice_config_t *config);
int config_rehash(void);
ice_config_locks *config_locks(void);
ice_config_t *config_get_config(void);
void config_release_config(void);
/* To be used ONLY in one-time startup code */
ice_config_t *config_get_config_unlocked(void);
#endif /* __CONFIG_H__ */

View File

@ -11,7 +11,7 @@ int main(void)
config_parse_file("icecast.xml");
config = config_get_config();
config = config_get_config_unlocked();
_dump_config(config);

View File

@ -40,6 +40,7 @@
#include "geturl.h"
#include "format.h"
#include "format_mp3.h"
#include "event.h"
#define CATMODULE "connection"
@ -112,6 +113,10 @@ connection_t *create_connection(sock_t sock, char *ip) {
con->con_time = time(NULL);
con->id = _next_connection_id();
con->ip = ip;
con->event_number = EVENT_NO_EVENT;
con->event = NULL;
return con;
}
@ -209,10 +214,13 @@ static void _build_pool(void)
int i;
thread_type *tid;
char buff[64];
int threadpool_size;
config = config_get_config();
threadpool_size = config->threadpool_size;
config_release_config();
for (i = 0; i < config->threadpool_size; i++) {
for (i = 0; i < threadpool_size; i++) {
snprintf(buff, 64, "Connection Thread #%d", i);
tid = thread_create(buff, _handle_connection, NULL, THREAD_ATTACHED);
_push_thread(&_conhands, tid);
@ -290,6 +298,16 @@ static connection_t *_get_connection(void)
return con;
}
void connection_inject_event(int eventnum, void *event_data) {
connection_t *con = calloc(1, sizeof(connection_t));
con->event_number = eventnum;
con->event = event_data;
_add_connection(con);
_signal_pool();
}
/* TODO: Make this return an appropriate error code so that we can use HTTP
* codes where appropriate
*/
@ -297,12 +315,18 @@ int connection_create_source(client_t *client, connection_t *con, http_parser_t
source_t *source;
char *contenttype;
mount_proxy *mountproxy, *mountinfo = NULL;
int source_limit;
ice_config_t *config;
config = config_get_config();
source_limit = config->source_limit;
config_release_config();
/* check to make sure this source wouldn't
** be over the limit
*/
global_lock();
if (global.sources >= config_get_config()->source_limit) {
if (global.sources >= source_limit) {
INFO1("Source (%s) logged in, but there are too many sources", mount);
global_unlock();
return 0;
@ -312,7 +336,11 @@ int connection_create_source(client_t *client, connection_t *con, http_parser_t
stats_event_inc(NULL, "sources");
mountproxy = config_get_config()->mounts;
config = config_get_config();
mountproxy = config->mounts;
thread_mutex_lock(&(config_locks()->mounts_lock));
config_release_config();
while(mountproxy) {
if(!strcmp(mountproxy->mountname, mount)) {
mountinfo = mountproxy;
@ -327,15 +355,18 @@ int connection_create_source(client_t *client, connection_t *con, http_parser_t
format_type_t format = format_get_type(contenttype);
if (format == FORMAT_ERROR) {
WARN1("Content-type \"%s\" not supported, dropping source", contenttype);
thread_mutex_unlock(&(config_locks()->mounts_lock));
goto fail;
} else {
source = source_create(client, con, parser, mount,
format, mountinfo);
thread_mutex_unlock(&(config_locks()->mounts_lock));
}
} else {
format_type_t format = FORMAT_TYPE_MP3;
ERROR0("No content-type header, falling back to backwards compatibility mode for icecast 1.x relays. Assuming content is mp3.");
source = source_create(client, con, parser, mount, format, mountinfo);
thread_mutex_unlock(&(config_locks()->mounts_lock));
}
source->send_return = 1;
@ -408,17 +439,22 @@ static int _check_pass_ice(http_parser_t *parser, char *correctpass)
static int _check_relay_pass(http_parser_t *parser)
{
char *pass = config_get_config()->relay_password;
ice_config_t *config = config_get_config();
char *pass = config->relay_password;
if(!pass)
pass = config_get_config()->source_password;
pass = config->source_password;
config_release_config();
return _check_pass_http(parser, "relay", pass);
}
static int _check_admin_pass(http_parser_t *parser)
{
char *pass = config_get_config()->admin_password;
char *user = config_get_config()->admin_username;
ice_config_t *config = config_get_config();
char *pass = config->admin_password;
char *user = config->admin_username;
config_release_config();
if(!pass || !user)
return 0;
@ -427,11 +463,16 @@ static int _check_admin_pass(http_parser_t *parser)
static int _check_source_pass(http_parser_t *parser, char *mount)
{
char *pass = config_get_config()->source_password;
ice_config_t *config = config_get_config();
char *pass = config->source_password;
char *user = "source";
int ret;
int ice_login = config->ice_login;
mount_proxy *mountinfo = config->mounts;
thread_mutex_lock(&(config_locks()->mounts_lock));
config_release_config();
mount_proxy *mountinfo = config_get_config()->mounts;
while(mountinfo) {
if(!strcmp(mountinfo->mountname, mount)) {
if(mountinfo->password)
@ -443,13 +484,15 @@ static int _check_source_pass(http_parser_t *parser, char *mount)
mountinfo = mountinfo->next;
}
thread_mutex_unlock(&(config_locks()->mounts_lock));
if(!pass) {
WARN0("No source password set, rejecting source");
return 0;
}
ret = _check_pass_http(parser, user, pass);
if(!ret && config_get_config()->ice_login)
if(!ret && ice_login)
{
ret = _check_pass_ice(parser, pass);
if(ret)
@ -627,6 +670,19 @@ static void _handle_get_request(connection_t *con,
int bytes;
struct stat statbuf;
source_t *source;
int fileserve;
char *host;
int port;
ice_config_t *config;
int client_limit;
config = config_get_config();
fileserve = config->fileserve;
host = config->hostname;
port = config->port;
client_limit = config->client_limit;
config_release_config();
DEBUG0("Client connected");
@ -689,8 +745,8 @@ static void _handle_get_request(connection_t *con,
free(fullpath);
return;
}
else if(config_get_config()->fileserve &&
stat(fullpath, &statbuf) == 0) {
else if(fileserve && stat(fullpath, &statbuf) == 0)
{
fserve_client_create(client, fullpath);
free(fullpath);
return;
@ -709,14 +765,14 @@ static void _handle_get_request(connection_t *con,
"HTTP/1.0 200 OK\r\n"
"Content-Type: audio/x-mpegurl\r\n\r\n"
"http://%s:%d%s",
config_get_config()->hostname,
config_get_config()->port,
host,
port,
sourceuri
);
if(bytes > 0) client->con->sent_bytes = bytes;
client_destroy(client);
}
else if(config_get_config()->fileserve) {
else if(fileserve) {
fullpath = util_get_path_from_normalised_uri(sourceuri);
if(stat(fullpath, &statbuf) == 0) {
fserve_client_create(client, fullpath);
@ -774,7 +830,7 @@ static void _handle_get_request(connection_t *con,
}
global_lock();
if (global.clients >= config_get_config()->client_limit) {
if (global.clients >= client_limit) {
client_send_504(client,
"The server is already full. Try again later.");
global_unlock();
@ -788,7 +844,7 @@ static void _handle_get_request(connection_t *con,
DEBUG0("Source found for client");
global_lock();
if (global.clients >= config_get_config()->client_limit) {
if (global.clients >= client_limit) {
client_send_504(client,
"The server is already full. Try again later.");
global_unlock();
@ -847,6 +903,21 @@ static void *_handle_connection(void *arg)
/* grab a connection and set the socket to blocking */
while ((con = _get_connection())) {
/* Handle meta-connections */
if(con->event_number > 0) {
switch(con->event_number) {
case EVENT_CONFIG_READ:
event_config_read(con->event);
break;
default:
ERROR1("Unknown event number: %d", con->event_number);
break;
}
free(con);
continue;
}
stats_event_inc(NULL, "connections");
sock_set_blocking(con->sock, SOCK_BLOCK);

View File

@ -21,6 +21,10 @@ typedef struct connection_tag
char *ip;
char *host;
/* For 'fake' connections */
int event_number;
void *event;
} connection_t;
void connection_initialize(void);
@ -31,6 +35,8 @@ connection_t *create_connection(sock_t sock, char *ip);
int connection_create_source(struct _client_tag *client, connection_t *con,
http_parser_t *parser, char *mount);
void connection_inject_event(int eventnum, void *event_data);
extern rwlock_t _source_shutdown_rwlock;
#endif /* __CONNECTION_H__ */

46
src/event.c Normal file
View File

@ -0,0 +1,46 @@
#include "event.h"
#include "config.h"
#include "refbuf.h"
#include "client.h"
#include "logging.h"
#define CATMODULE "event"
void event_config_read(void *arg)
{
int ret;
ice_config_t *config;
ice_config_t new_config;
/* reread config file */
config = config_get_config(); /* Both to get the lock, and to be able
to find out the config filename */
ret = config_parse_file(config->config_filename, &new_config);
if(ret < 0) {
ERROR0("Error parsing config, not replacing existing config");
switch(ret) {
case CONFIG_EINSANE:
ERROR0("Config filename null or blank");
break;
case CONFIG_ENOROOT:
ERROR1("Root element not found in %s", config->config_filename);
break;
case CONFIG_EBADROOT:
ERROR1("Not an icecast2 config file: %s",
config->config_filename);
break;
default:
ERROR1("Parse error in reading %s", config->config_filename);
break;
}
config_release_config();
}
else {
config_clear(config);
config_set_config(&new_config);
config_release_config();
}
}

9
src/event.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef __EVENT_H__
#define __EVENT_H__
#define EVENT_NO_EVENT 0
#define EVENT_CONFIG_READ 1
void event_config_read(void *nothing);
#endif /* __EVENT_H__ */

View File

@ -78,7 +78,12 @@ static void create_mime_mappings(char *fn);
void fserve_initialize(void)
{
if(!config_get_config()->fileserve)
ice_config_t *config = config_get_config();
int serve = config->fileserve;
config_release_config();
if(!serve)
return;
create_mime_mappings(MIMETYPESFILE);
@ -95,7 +100,12 @@ void fserve_initialize(void)
void fserve_shutdown(void)
{
if(!config_get_config()->fileserve)
ice_config_t *config = config_get_config();
int serve = config->fileserve;
config_release_config();
if(!serve)
return;
if(!run_fserv)
@ -345,6 +355,11 @@ int fserve_client_create(client_t *httpclient, char *path)
{
fserve_t *client = calloc(1, sizeof(fserve_t));
int bytes;
int client_limit;
ice_config_t *config = config_get_config();
client_limit = config->client_limit;
config_release_config();
client->file = fopen(path, "rb");
if(!client->file) {
@ -358,7 +373,7 @@ int fserve_client_create(client_t *httpclient, char *path)
client->buf = malloc(BUFSIZE);
global_lock();
if(global.clients >= config_get_config()->client_limit) {
if(global.clients >= client_limit) {
httpclient->respcode = 504;
bytes = sock_write(httpclient->con->sock,
"HTTP/1.0 504 Server Full\r\n"

View File

@ -125,7 +125,7 @@ static int _start_logging(void)
{
char fn_error[FILENAME_MAX];
char fn_access[FILENAME_MAX];
ice_config_t *config = config_get_config();
ice_config_t *config = config_get_config_unlocked();
if(strcmp(config->error_log, "-")) {
snprintf(fn_error, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->error_log);
@ -157,9 +157,10 @@ static int _setup_socket(void)
{
ice_config_t *config;
config = config_get_config();
config = config_get_config_unlocked();
global.serversock = sock_get_server_socket(config->port, config->bind_address);
if (global.serversock == SOCK_ERROR)
return 0;
@ -180,7 +181,8 @@ static int _start_listening(void)
static int _server_proc_init(void)
{
if (!_setup_socket()) {
fprintf(stderr, "Could not create listener socket on port %d\n", config_get_config()->port);
fprintf(stderr, "Could not create listener socket on port %d\n",
config_get_config_unlocked()->port);
return 0;
}
@ -205,7 +207,7 @@ static void _server_proc(void)
static void _ch_root_uid_setup(void)
{
ice_config_t *conf = config_get_config();
ice_config_t *conf = config_get_config_unlocked();
#ifdef CHUID
struct passwd *user;
struct group *group;
@ -291,7 +293,9 @@ int main(int argc, char **argv)
_initialize_subsystems();
/* parse the config file */
ret = config_parse_file(filename);
config_get_config();
ret = config_initial_parse_file(filename);
config_release_config();
if (ret < 0) {
fprintf(stderr, "FATAL: error parsing config file:");
switch (ret) {

View File

@ -10,6 +10,7 @@
#include "refbuf.h"
#include "client.h"
#include "logging.h"
#include "event.h"
#include "sighandler.h"
@ -34,16 +35,22 @@ void sighandler_initialize(void)
void _sig_hup(int signo)
{
INFO1("Caught signal %d, rehashing config and reopening logfiles (unimplemented)...", signo);
/* We do this elsewhere because it's a bad idea to hang around for too
* long re-reading an entire config file inside a signal handler. Bad
* practice.
*/
INFO1("Caught signal %d, scheduling config reread ...",
signo);
/* reread config file */
/* reopen logfiles */
connection_inject_event(EVENT_CONFIG_READ, NULL);
/* reopen logfiles (TODO: We don't do this currently) */
#ifdef __linux__
/* linux requires us to reattach the signal handler */
/* some OSes require us to reattach the signal handler */
signal(SIGHUP, _sig_hup);
#endif
}
void _sig_die(int signo)

View File

@ -49,11 +49,18 @@ thread_type *_slave_thread_id;
static int _initialized = 0;
void slave_initialize(void) {
ice_config_t *config;
if (_initialized) return;
config = config_get_config();
/* Don't create a slave thread if it isn't configured */
if (config_get_config()->master_server == NULL &&
config_get_config()->relay == NULL)
if (config->master_server == NULL &&
config->relay == NULL)
{
config_release_config();
return;
}
config_release_config();
_initialized = 1;
_slave_thread_id = thread_create("Slave Thread", _slave_thread, NULL, THREAD_ATTACHED);
@ -131,28 +138,48 @@ static void create_relay_stream(char *server, int port,
static void *_slave_thread(void *arg) {
sock_t mastersock;
char buf[256];
int interval = config_get_config()->master_update_interval;
int interval;
char *authheader, *data;
int len;
char *username = "relay";
char *password = config_get_config()->master_password;
char *password;
int max_interval;
relay_server *relay;
ice_config_t *config;
config = config_get_config();
password = config->master_password;
interval = max_interval = config->master_update_interval;
if(password == NULL)
password = config_get_config()->source_password;
password = config->source_password;
config_release_config();
while (_initialized) {
if (config_get_config()->master_update_interval > ++interval) {
if (max_interval > ++interval) {
thread_sleep(1000000);
continue;
}
else
interval = 0;
else {
/* In case it's been reconfigured */
config = config_get_config();
max_interval = config->master_update_interval;
config_release_config();
interval = 0;
}
config = config_get_config();
if(config->master_server != NULL) {
char *server = config->master_server;
int port = config->master_server_port;
config_release_config();
mastersock = sock_connect_wto(server, port, 0);
if(config_get_config()->master_server != NULL) {
mastersock = sock_connect_wto(config_get_config()->master_server,
config_get_config()->master_server_port, 0);
if (mastersock == SOCK_ERROR) {
WARN0("Relay slave failed to contact master server to fetch stream list");
continue;
@ -180,19 +207,23 @@ static void *_slave_thread(void *arg) {
if (!source_find_mount(buf)) {
avl_tree_unlock(global.source_tree);
create_relay_stream(
config_get_config()->master_server,
config_get_config()->master_server_port,
buf, NULL, 0);
create_relay_stream(server, port, buf, NULL, 0);
}
else
avl_tree_unlock(global.source_tree);
}
sock_close(mastersock);
}
else {
config_release_config();
}
/* And now, we process the individual mounts... */
relay = config_get_config()->relay;
config = config_get_config();
relay = config->relay;
thread_mutex_lock(&(config_locks()->relay_lock));
config_release_config();
while(relay) {
avl_tree_rlock(global.source_tree);
if(!source_find_mount(relay->localmount)) {
@ -205,6 +236,8 @@ static void *_slave_thread(void *arg) {
avl_tree_unlock(global.source_tree);
relay = relay->next;
}
thread_mutex_unlock(&(config_locks()->relay_lock));
}
thread_exit(0);
return NULL;

View File

@ -59,7 +59,6 @@ source_t *source_create(client_t *client, connection_t *con,
http_parser_t *parser, const char *mount, format_type_t type,
mount_proxy *mountinfo)
{
int i = 0;
source_t *src;
src = (source_t *)malloc(sizeof(source_t));
@ -79,17 +78,6 @@ source_t *source_create(client_t *client, connection_t *con,
src->dumpfilename = NULL;
src->dumpfile = NULL;
src->audio_info = util_dict_new();
for (i=0;i<config_get_config()->num_yp_directories;i++) {
if (config_get_config()->yp_url[i]) {
src->ypdata[src->num_yp_directories] = yp_create_ypdata();
src->ypdata[src->num_yp_directories]->yp_url =
config_get_config()->yp_url[i];
src->ypdata[src->num_yp_directories]->yp_url_timeout =
config_get_config()->yp_url_timeout[i];
src->ypdata[src->num_yp_directories]->yp_touch_interval = 0;
src->num_yp_directories++;
}
}
if(mountinfo != NULL) {
src->fallback_mount = mountinfo->fallback_mount;
@ -191,9 +179,31 @@ void *source_main(void *arg)
int suppress_yp = 0;
char *ai;
long queue_limit = config_get_config()->queue_size_limit;
long queue_limit;
ice_config_t *config;
char *hostname;
int port;
timeout = config_get_config()->source_timeout;
config = config_get_config();
queue_limit = config->queue_size_limit;
timeout = config->source_timeout;
hostname = config->hostname;
port = config->port;
for (i=0;i<config->num_yp_directories;i++) {
if (config->yp_url[i]) {
source->ypdata[source->num_yp_directories] = yp_create_ypdata();
source->ypdata[source->num_yp_directories]->yp_url =
config->yp_url[i];
source->ypdata[source->num_yp_directories]->yp_url_timeout =
config->yp_url_timeout[i];
source->ypdata[source->num_yp_directories]->yp_touch_interval = 0;
source->num_yp_directories++;
}
}
config_release_config();
/* grab a read lock, to make sure we get a chance to cleanup */
thread_rwlock_rlock(source->shutdown_rwlock);
@ -273,12 +283,11 @@ void *source_main(void *arg)
}
/* 6 for max size of port */
listen_url_size = strlen("http://") +
strlen(config_get_config()->hostname) +
strlen(hostname) +
strlen(":") + 6 + strlen(source->mount) + 1;
source->ypdata[i]->listen_url = malloc(listen_url_size);
sprintf(source->ypdata[i]->listen_url, "http://%s:%d%s",
config_get_config()->hostname, config_get_config()->port,
source->mount);
hostname, port, source->mount);
}
if(!suppress_yp) {
@ -609,6 +618,9 @@ done:
global.sources--;
global_unlock();
if(source->dumpfile)
fclose(source->dumpfile);
/* release our hold on the lock so the main thread can continue cleaning up */
thread_rwlock_unlock(source->shutdown_rwlock);
@ -616,9 +628,6 @@ done:
avl_delete(global.source_tree, source, source_free_source);
avl_tree_unlock(global.source_tree);
if(source->dumpfile)
fclose(source->dumpfile);
thread_exit(0);
return NULL;

View File

@ -74,8 +74,11 @@ int util_read_header(int sock, char *buff, unsigned long len)
unsigned long pos;
char c;
ice_config_t *config;
int header_timeout;
config = config_get_config();
header_timeout = config->header_timeout;
config_release_config();
read_bytes = 1;
pos = 0;
@ -84,7 +87,7 @@ int util_read_header(int sock, char *buff, unsigned long len)
while ((read_bytes == 1) && (pos < (len - 1))) {
read_bytes = 0;
if (util_timed_wait_for_fd(sock, config->header_timeout*1000) > 0) {
if (util_timed_wait_for_fd(sock, header_timeout*1000) > 0) {
if ((read_bytes = recv(sock, &c, 1, 0))) {
if (c != '\r') buff[pos++] = c;
@ -199,9 +202,14 @@ char *util_get_path_from_uri(char *uri) {
char *util_get_path_from_normalised_uri(char *uri) {
char *fullpath;
char *webroot;
ice_config_t *config = config_get_config();
fullpath = malloc(strlen(uri) + strlen(config_get_config()->webroot_dir) + 1);
strcpy(fullpath, config_get_config()->webroot_dir);
webroot = config->webroot_dir;
config_release_config();
fullpath = malloc(strlen(uri) + strlen(webroot) + 1);
strcpy(fullpath, webroot);
strcat(fullpath, uri);

View File

@ -15,14 +15,18 @@
#define CATMODULE "yp"
int yp_submit_url(int curl_con, char *yp_url, char *url, char *type)
int yp_submit_url(int curl_con, char *yp_url, char *url, char *type, int i)
{
int ret = 0;
int *timeout;
ice_config_t *config = config_get_config();
timeout = config->yp_url_timeout + i;
config_release_config();
curl_easy_setopt(curl_get_handle(curl_con), CURLOPT_URL, yp_url);
curl_easy_setopt(curl_get_handle(curl_con), CURLOPT_POSTFIELDS, url);
curl_easy_setopt(curl_get_handle(curl_con), CURLOPT_TIMEOUT,
config_get_config()->yp_url_timeout);
curl_easy_setopt(curl_get_handle(curl_con), CURLOPT_TIMEOUT, timeout);
/* get it! */
memset(curl_get_result(curl_con), 0, sizeof(struct curl_memory_struct));
@ -93,7 +97,7 @@ int yp_remove(source_t *source)
else {
/* specify URL to get */
ret = yp_submit_url(curl_con, source->ypdata[i]->yp_url,
url, "yp_remove");
url, "yp_remove", i);
}
if (url) {
free(url);
@ -159,7 +163,7 @@ int yp_touch(source_t *source)
else {
/* specify URL to get */
ret = yp_submit_url(curl_con, source->ypdata[i]->yp_url,
url, "yp_touch");
url, "yp_touch", i);
if (!ret) {
source->ypdata[i]->sid[0] = 0;
}
@ -291,7 +295,7 @@ int yp_add(source_t *source, int which)
else {
/* specify URL to get */
ret = yp_submit_url(curl_con, source->ypdata[i]->yp_url,
url, "yp_add");
url, "yp_add", i);
if (ret) {
if (strlen(curl_get_header_result(curl_con)->sid) > 0) {