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 2003-03-05
bug fixes) 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 2003-03-02
More features: More features:

6
TODO
View File

@ -50,6 +50,8 @@ FEATURES
- option to use ipv6 (equiv to using <bind-address>::</bindaddress>, I think. - 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\ 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\ 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\ 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\ 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\ icecast_LDADD = net/libicenet.la thread/libicethread.la httpp/libicehttpp.la\
log/libicelog.la avl/libiceavl.la timing/libicetiming.la log/libicelog.la avl/libiceavl.la timing/libicetiming.la

View File

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

View File

@ -8,6 +8,8 @@
#define MAX_YP_DIRECTORIES 25 #define MAX_YP_DIRECTORIES 25
#include "thread/thread.h"
typedef struct ice_config_dir_tag typedef struct ice_config_dir_tag
{ {
char *host; char *host;
@ -40,6 +42,8 @@ typedef struct _mount_proxy {
typedef struct ice_config_tag typedef struct ice_config_tag
{ {
char *config_filename;
char *location; char *location;
char *admin; char *admin;
@ -90,15 +94,30 @@ typedef struct ice_config_tag
int num_yp_directories; int num_yp_directories;
} ice_config_t; } 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_initialize(void);
void config_shutdown(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); 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); int config_rehash(void);
ice_config_locks *config_locks(void);
ice_config_t *config_get_config(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__ */ #endif /* __CONFIG_H__ */

View File

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

View File

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

View File

@ -21,6 +21,10 @@ typedef struct connection_tag
char *ip; char *ip;
char *host; char *host;
/* For 'fake' connections */
int event_number;
void *event;
} connection_t; } connection_t;
void connection_initialize(void); 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, int connection_create_source(struct _client_tag *client, connection_t *con,
http_parser_t *parser, char *mount); http_parser_t *parser, char *mount);
void connection_inject_event(int eventnum, void *event_data);
extern rwlock_t _source_shutdown_rwlock; extern rwlock_t _source_shutdown_rwlock;
#endif /* __CONNECTION_H__ */ #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) 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; return;
create_mime_mappings(MIMETYPESFILE); create_mime_mappings(MIMETYPESFILE);
@ -95,7 +100,12 @@ void fserve_initialize(void)
void fserve_shutdown(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; return;
if(!run_fserv) if(!run_fserv)
@ -345,6 +355,11 @@ int fserve_client_create(client_t *httpclient, char *path)
{ {
fserve_t *client = calloc(1, sizeof(fserve_t)); fserve_t *client = calloc(1, sizeof(fserve_t));
int bytes; 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"); client->file = fopen(path, "rb");
if(!client->file) { if(!client->file) {
@ -358,7 +373,7 @@ int fserve_client_create(client_t *httpclient, char *path)
client->buf = malloc(BUFSIZE); client->buf = malloc(BUFSIZE);
global_lock(); global_lock();
if(global.clients >= config_get_config()->client_limit) { if(global.clients >= client_limit) {
httpclient->respcode = 504; httpclient->respcode = 504;
bytes = sock_write(httpclient->con->sock, bytes = sock_write(httpclient->con->sock,
"HTTP/1.0 504 Server Full\r\n" "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_error[FILENAME_MAX];
char fn_access[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, "-")) { if(strcmp(config->error_log, "-")) {
snprintf(fn_error, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, 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; ice_config_t *config;
config = config_get_config(); config = config_get_config_unlocked();
global.serversock = sock_get_server_socket(config->port, config->bind_address); global.serversock = sock_get_server_socket(config->port, config->bind_address);
if (global.serversock == SOCK_ERROR) if (global.serversock == SOCK_ERROR)
return 0; return 0;
@ -180,7 +181,8 @@ static int _start_listening(void)
static int _server_proc_init(void) static int _server_proc_init(void)
{ {
if (!_setup_socket()) { 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; return 0;
} }
@ -205,7 +207,7 @@ static void _server_proc(void)
static void _ch_root_uid_setup(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 #ifdef CHUID
struct passwd *user; struct passwd *user;
struct group *group; struct group *group;
@ -291,7 +293,9 @@ int main(int argc, char **argv)
_initialize_subsystems(); _initialize_subsystems();
/* parse the config file */ /* parse the config file */
ret = config_parse_file(filename); config_get_config();
ret = config_initial_parse_file(filename);
config_release_config();
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "FATAL: error parsing config file:"); fprintf(stderr, "FATAL: error parsing config file:");
switch (ret) { switch (ret) {

View File

@ -10,6 +10,7 @@
#include "refbuf.h" #include "refbuf.h"
#include "client.h" #include "client.h"
#include "logging.h" #include "logging.h"
#include "event.h"
#include "sighandler.h" #include "sighandler.h"
@ -34,16 +35,22 @@ void sighandler_initialize(void)
void _sig_hup(int signo) 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 */ /* reread config file */
/* reopen logfiles */ connection_inject_event(EVENT_CONFIG_READ, NULL);
/* reopen logfiles (TODO: We don't do this currently) */
#ifdef __linux__ /* some OSes require us to reattach the signal handler */
/* linux requires us to reattach the signal handler */
signal(SIGHUP, _sig_hup); signal(SIGHUP, _sig_hup);
#endif
} }
void _sig_die(int signo) void _sig_die(int signo)

View File

@ -49,11 +49,18 @@ thread_type *_slave_thread_id;
static int _initialized = 0; static int _initialized = 0;
void slave_initialize(void) { void slave_initialize(void) {
ice_config_t *config;
if (_initialized) return; if (_initialized) return;
config = config_get_config();
/* Don't create a slave thread if it isn't configured */ /* Don't create a slave thread if it isn't configured */
if (config_get_config()->master_server == NULL && if (config->master_server == NULL &&
config_get_config()->relay == NULL) config->relay == NULL)
{
config_release_config();
return; return;
}
config_release_config();
_initialized = 1; _initialized = 1;
_slave_thread_id = thread_create("Slave Thread", _slave_thread, NULL, THREAD_ATTACHED); _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) { static void *_slave_thread(void *arg) {
sock_t mastersock; sock_t mastersock;
char buf[256]; char buf[256];
int interval = config_get_config()->master_update_interval; int interval;
char *authheader, *data; char *authheader, *data;
int len; int len;
char *username = "relay"; char *username = "relay";
char *password = config_get_config()->master_password; char *password;
int max_interval;
relay_server *relay; 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) if(password == NULL)
password = config_get_config()->source_password; password = config->source_password;
config_release_config();
while (_initialized) { while (_initialized) {
if (config_get_config()->master_update_interval > ++interval) { if (max_interval > ++interval) {
thread_sleep(1000000); thread_sleep(1000000);
continue; continue;
} }
else else {
interval = 0; /* 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) { if (mastersock == SOCK_ERROR) {
WARN0("Relay slave failed to contact master server to fetch stream list"); WARN0("Relay slave failed to contact master server to fetch stream list");
continue; continue;
@ -180,19 +207,23 @@ static void *_slave_thread(void *arg) {
if (!source_find_mount(buf)) { if (!source_find_mount(buf)) {
avl_tree_unlock(global.source_tree); avl_tree_unlock(global.source_tree);
create_relay_stream( create_relay_stream(server, port, buf, NULL, 0);
config_get_config()->master_server,
config_get_config()->master_server_port,
buf, NULL, 0);
} }
else else
avl_tree_unlock(global.source_tree); avl_tree_unlock(global.source_tree);
} }
sock_close(mastersock); sock_close(mastersock);
} }
else {
config_release_config();
}
/* And now, we process the individual mounts... */ /* 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) { while(relay) {
avl_tree_rlock(global.source_tree); avl_tree_rlock(global.source_tree);
if(!source_find_mount(relay->localmount)) { if(!source_find_mount(relay->localmount)) {
@ -205,6 +236,8 @@ static void *_slave_thread(void *arg) {
avl_tree_unlock(global.source_tree); avl_tree_unlock(global.source_tree);
relay = relay->next; relay = relay->next;
} }
thread_mutex_unlock(&(config_locks()->relay_lock));
} }
thread_exit(0); thread_exit(0);
return NULL; 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, http_parser_t *parser, const char *mount, format_type_t type,
mount_proxy *mountinfo) mount_proxy *mountinfo)
{ {
int i = 0;
source_t *src; source_t *src;
src = (source_t *)malloc(sizeof(source_t)); 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->dumpfilename = NULL;
src->dumpfile = NULL; src->dumpfile = NULL;
src->audio_info = util_dict_new(); 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) { if(mountinfo != NULL) {
src->fallback_mount = mountinfo->fallback_mount; src->fallback_mount = mountinfo->fallback_mount;
@ -191,9 +179,31 @@ void *source_main(void *arg)
int suppress_yp = 0; int suppress_yp = 0;
char *ai; 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 */ /* grab a read lock, to make sure we get a chance to cleanup */
thread_rwlock_rlock(source->shutdown_rwlock); thread_rwlock_rlock(source->shutdown_rwlock);
@ -273,12 +283,11 @@ void *source_main(void *arg)
} }
/* 6 for max size of port */ /* 6 for max size of port */
listen_url_size = strlen("http://") + listen_url_size = strlen("http://") +
strlen(config_get_config()->hostname) + strlen(hostname) +
strlen(":") + 6 + strlen(source->mount) + 1; strlen(":") + 6 + strlen(source->mount) + 1;
source->ypdata[i]->listen_url = malloc(listen_url_size); source->ypdata[i]->listen_url = malloc(listen_url_size);
sprintf(source->ypdata[i]->listen_url, "http://%s:%d%s", sprintf(source->ypdata[i]->listen_url, "http://%s:%d%s",
config_get_config()->hostname, config_get_config()->port, hostname, port, source->mount);
source->mount);
} }
if(!suppress_yp) { if(!suppress_yp) {
@ -609,6 +618,9 @@ done:
global.sources--; global.sources--;
global_unlock(); global_unlock();
if(source->dumpfile)
fclose(source->dumpfile);
/* release our hold on the lock so the main thread can continue cleaning up */ /* release our hold on the lock so the main thread can continue cleaning up */
thread_rwlock_unlock(source->shutdown_rwlock); thread_rwlock_unlock(source->shutdown_rwlock);
@ -616,9 +628,6 @@ done:
avl_delete(global.source_tree, source, source_free_source); avl_delete(global.source_tree, source, source_free_source);
avl_tree_unlock(global.source_tree); avl_tree_unlock(global.source_tree);
if(source->dumpfile)
fclose(source->dumpfile);
thread_exit(0); thread_exit(0);
return NULL; return NULL;

View File

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

View File

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