config.c 26.8 KB
Newer Older
Jack Moffitt's avatar
Jack Moffitt committed
1 2 3
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Michael Smith's avatar
Michael Smith committed
4 5
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
Michael Smith's avatar
Michael Smith committed
6 7

#include "thread/thread.h"
Jack Moffitt's avatar
Jack Moffitt committed
8
#include "config.h"
9 10 11
#include "refbuf.h"
#include "client.h"
#include "logging.h" 
Jack Moffitt's avatar
Jack Moffitt committed
12

13
#define CATMODULE "CONFIG"
Jack Moffitt's avatar
Jack Moffitt committed
14 15 16 17
#define CONFIG_DEFAULT_LOCATION "Earth"
#define CONFIG_DEFAULT_ADMIN "icemaster@localhost"
#define CONFIG_DEFAULT_CLIENT_LIMIT 256
#define CONFIG_DEFAULT_SOURCE_LIMIT 16
18
#define CONFIG_DEFAULT_QUEUE_SIZE_LIMIT (100*1024)
Jack Moffitt's avatar
Jack Moffitt committed
19 20 21
#define CONFIG_DEFAULT_THREADPOOL_SIZE 4
#define CONFIG_DEFAULT_CLIENT_TIMEOUT 30
#define CONFIG_DEFAULT_HEADER_TIMEOUT 15
22
#define CONFIG_DEFAULT_SOURCE_TIMEOUT 10
Jack Moffitt's avatar
Jack Moffitt committed
23
#define CONFIG_DEFAULT_SOURCE_PASSWORD "changeme"
24
#define CONFIG_DEFAULT_RELAY_PASSWORD "changeme"
25
#define CONFIG_DEFAULT_ICE_LOGIN 0
26
#define CONFIG_DEFAULT_FILESERVE 1
Jack Moffitt's avatar
Jack Moffitt committed
27 28 29 30
#define CONFIG_DEFAULT_TOUCH_FREQ 5
#define CONFIG_DEFAULT_HOSTNAME "localhost"
#define CONFIG_DEFAULT_ACCESS_LOG "access.log"
#define CONFIG_DEFAULT_ERROR_LOG "error.log"
31
#define CONFIG_DEFAULT_LOG_LEVEL 4
32 33 34 35
#define CONFIG_DEFAULT_CHROOT 0
#define CONFIG_DEFAULT_CHUID 0
#define CONFIG_DEFAULT_USER NULL
#define CONFIG_DEFAULT_GROUP NULL
36
#define CONFIG_MASTER_UPDATE_INTERVAL 120
37
#define CONFIG_YP_URL_TIMEOUT 10
Jack Moffitt's avatar
Jack Moffitt committed
38

39 40 41
#ifndef _WIN32
#define CONFIG_DEFAULT_BASE_DIR "/usr/local/icecast"
#define CONFIG_DEFAULT_LOG_DIR "/usr/local/icecast/logs"
42
#define CONFIG_DEFAULT_WEBROOT_DIR "/usr/local/icecast/webroot"
43 44 45
#else
#define CONFIG_DEFAULT_BASE_DIR ".\\"
#define CONFIG_DEFAULT_LOG_DIR ".\\logs"
46
#define CONFIG_DEFAULT_WEBROOT_DIR ".\\webroot"
47 48
#endif

Michael Smith's avatar
Michael Smith committed
49 50 51 52 53 54 55 56 57 58 59 60 61 62
ice_config_t _current_configuration;
ice_config_locks _locks;

static void _set_defaults(ice_config_t *c);
static void _parse_root(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_limits(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_directory(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_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);
63 64
static void _parse_listen_socket(xmlDocPtr doc, xmlNodePtr node, 
        ice_config_t *c);
Michael Smith's avatar
Michael Smith committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
static void _add_server(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);

static void create_locks() {
    thread_mutex_create(&_locks.relay_lock);
    thread_mutex_create(&_locks.mounts_lock);
    thread_mutex_create(&_locks.config_lock);
}

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)
Jack Moffitt's avatar
Jack Moffitt committed
91
{
Michael Smith's avatar
Michael Smith committed
92 93
	memset(configuration, 0, sizeof(ice_config_t));
	_set_defaults(configuration);
Jack Moffitt's avatar
Jack Moffitt committed
94 95
}

Michael Smith's avatar
Michael Smith committed
96
void config_clear(ice_config_t *c)
Jack Moffitt's avatar
Jack Moffitt committed
97
{
98
	ice_config_dir_t *dirnode, *nextdirnode;
99
    relay_server *relay, *nextrelay;
100
    mount_proxy *mount, *nextmount;
101
    int i;
Jack Moffitt's avatar
Jack Moffitt committed
102

Michael Smith's avatar
Michael Smith committed
103 104
    if (c->config_filename)
        free(c->config_filename);
105 106 107 108 109 110 111

	if (c->location && c->location != CONFIG_DEFAULT_LOCATION) 
        xmlFree(c->location);
	if (c->admin && c->admin != CONFIG_DEFAULT_ADMIN) 
        xmlFree(c->admin);
	if (c->source_password && c->source_password != CONFIG_DEFAULT_SOURCE_PASSWORD)
        xmlFree(c->source_password);
112 113
	if (c->relay_password && c->relay_password != CONFIG_DEFAULT_SOURCE_PASSWORD)
        xmlFree(c->relay_password);
114 115 116 117
	if (c->admin_username)
        xmlFree(c->admin_username);
	if (c->admin_password)
        xmlFree(c->admin_password);
118 119 120 121 122 123
	if (c->hostname && c->hostname != CONFIG_DEFAULT_HOSTNAME) 
        xmlFree(c->hostname);
	if (c->base_dir && c->base_dir != CONFIG_DEFAULT_BASE_DIR) 
        xmlFree(c->base_dir);
	if (c->log_dir && c->log_dir != CONFIG_DEFAULT_LOG_DIR) 
        xmlFree(c->log_dir);
Michael Smith's avatar
Michael Smith committed
124
    if (c->webroot_dir && c->webroot_dir != CONFIG_DEFAULT_WEBROOT_DIR)
125
        xmlFree(c->webroot_dir);
126 127 128 129
	if (c->access_log && c->access_log != CONFIG_DEFAULT_ACCESS_LOG) 
        xmlFree(c->access_log);
	if (c->error_log && c->error_log != CONFIG_DEFAULT_ERROR_LOG) 
        xmlFree(c->error_log);
130 131 132
    for(i=0; i < MAX_LISTEN_SOCKETS; i++) {
        if (c->listeners[i].bind_address) xmlFree(c->listeners[i].bind_address);
    }
133 134
    if (c->master_server) xmlFree(c->master_server);
    if (c->master_password) xmlFree(c->master_password);
135 136
    if (c->user) xmlFree(c->user);
    if (c->group) xmlFree(c->group);
Michael Smith's avatar
Michael Smith committed
137 138 139

    thread_mutex_lock(&(_locks.relay_lock));
    relay = c->relay;
140 141 142 143
    while(relay) {
        nextrelay = relay->next;
        xmlFree(relay->server);
        xmlFree(relay->mount);
144 145
        if(relay->localmount)
            xmlFree(relay->localmount);
146 147 148
        free(relay);
        relay = nextrelay;
    }
Michael Smith's avatar
Michael Smith committed
149 150 151 152
    thread_mutex_unlock(&(_locks.relay_lock));

    thread_mutex_lock(&(_locks.mounts_lock));
    mount = c->mounts;
153 154 155 156 157 158 159 160 161 162
    while(mount) {
        nextmount = mount->next;
        xmlFree(mount->mountname);
        xmlFree(mount->username);
        xmlFree(mount->password);
        xmlFree(mount->dumpfile);
        xmlFree(mount->fallback_mount);
        free(mount);
        mount = nextmount;
    }
Michael Smith's avatar
Michael Smith committed
163 164 165
    thread_mutex_unlock(&(_locks.mounts_lock));

    dirnode = c->dir_list;
166 167
    while(dirnode) {
        nextdirnode = dirnode->next;
168
        xmlFree(dirnode->host);
169 170 171
        free(dirnode);
        dirnode = nextdirnode;
    }
Jack Moffitt's avatar
Jack Moffitt committed
172

173
    memset(c, 0, sizeof(ice_config_t));
Jack Moffitt's avatar
Jack Moffitt committed
174 175
}

Michael Smith's avatar
Michael Smith committed
176 177 178 179 180 181 182
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)
Jack Moffitt's avatar
Jack Moffitt committed
183 184 185 186 187 188
{
	xmlDocPtr doc;
	xmlNodePtr node;

	if (filename == NULL || strcmp(filename, "") == 0) return CONFIG_EINSANE;
	
Michael Smith's avatar
Michael Smith committed
189
    xmlInitParser();
Michael Smith's avatar
Michael Smith committed
190
	doc = xmlParseFile(filename);
Jack Moffitt's avatar
Jack Moffitt committed
191
	if (doc == NULL) {
192
		return CONFIG_EPARSE;
Jack Moffitt's avatar
Jack Moffitt committed
193 194 195 196 197
	}

	node = xmlDocGetRootElement(doc);
	if (node == NULL) {
		xmlFreeDoc(doc);
Michael Smith's avatar
Michael Smith committed
198
        xmlCleanupParser();
Jack Moffitt's avatar
Jack Moffitt committed
199 200 201 202 203
		return CONFIG_ENOROOT;
	}

	if (strcmp(node->name, "icecast") != 0) {
		xmlFreeDoc(doc);
Michael Smith's avatar
Michael Smith committed
204
        xmlCleanupParser();
Jack Moffitt's avatar
Jack Moffitt committed
205 206 207
		return CONFIG_EBADROOT;
	}

Michael Smith's avatar
Michael Smith committed
208 209 210 211 212
    config_init_configuration(configuration);

	configuration->config_filename = (char *)strdup(filename);

	_parse_root(doc, node->xmlChildrenNode, configuration);
Jack Moffitt's avatar
Jack Moffitt committed
213 214

	xmlFreeDoc(doc);
Michael Smith's avatar
Michael Smith committed
215
    xmlCleanupParser();
Jack Moffitt's avatar
Jack Moffitt committed
216 217 218 219 220 221 222 223 224

	return 0;
}

int config_parse_cmdline(int arg, char **argv)
{
	return 0;
}

Michael Smith's avatar
Michael Smith committed
225
ice_config_locks *config_locks(void)
Jack Moffitt's avatar
Jack Moffitt committed
226
{
Michael Smith's avatar
Michael Smith committed
227 228 229 230 231 232
    return &_locks;
}

void config_release_config(void)
{
    thread_mutex_unlock(&(_locks.config_lock));
Jack Moffitt's avatar
Jack Moffitt committed
233 234 235 236
}

ice_config_t *config_get_config(void)
{
Michael Smith's avatar
Michael Smith committed
237 238 239 240 241 242 243 244 245 246 247 248
    thread_mutex_lock(&(_locks.config_lock));
	return &_current_configuration;
}

/* 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)
{
	return &_current_configuration;
Jack Moffitt's avatar
Jack Moffitt committed
249 250
}

Michael Smith's avatar
Michael Smith committed
251
static void _set_defaults(ice_config_t *configuration)
Jack Moffitt's avatar
Jack Moffitt committed
252
{
Michael Smith's avatar
Michael Smith committed
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
	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;
269 270 271
    configuration->port = 0;
	configuration->listeners[0].port = 0;
	configuration->listeners[0].bind_address = NULL;
Michael Smith's avatar
Michael Smith committed
272
	configuration->master_server = NULL;
273
	configuration->master_server_port = 0;
Michael Smith's avatar
Michael Smith committed
274 275 276 277 278 279 280 281 282 283 284 285 286
    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;
Jack Moffitt's avatar
Jack Moffitt committed
287 288
}

Michael Smith's avatar
Michael Smith committed
289 290
static void _parse_root(xmlDocPtr doc, xmlNodePtr node, 
        ice_config_t *configuration)
Jack Moffitt's avatar
Jack Moffitt committed
291 292 293 294 295 296 297 298
{
	char *tmp;

	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "location") == 0) {
Michael Smith's avatar
Michael Smith committed
299 300
			if (configuration->location && configuration->location != CONFIG_DEFAULT_LOCATION) xmlFree(configuration->location);
			configuration->location = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Jack Moffitt's avatar
Jack Moffitt committed
301
		} else if (strcmp(node->name, "admin") == 0) {
Michael Smith's avatar
Michael Smith committed
302 303
			if (configuration->admin && configuration->admin != CONFIG_DEFAULT_ADMIN) xmlFree(configuration->admin);
			configuration->admin = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
304
		} else if(strcmp(node->name, "authentication") == 0) {
Michael Smith's avatar
Michael Smith committed
305
			_parse_authentication(doc, node->xmlChildrenNode, configuration);
306 307
        } else if (strcmp(node->name, "source-password") == 0) {
            /* TODO: This is the backwards-compatibility location */
308 309 310 311 312 313
            char *mount, *pass;
            if ((mount = (char *)xmlGetProp(node, "mount")) != NULL) {
                pass = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
                /* FIXME: This is a placeholder for per-mount passwords */
            }
            else {
Michael Smith's avatar
Michael Smith committed
314 315
			    if (configuration->source_password && configuration->source_password != CONFIG_DEFAULT_SOURCE_PASSWORD) xmlFree(configuration->source_password);
			    configuration->source_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
316
            }
317
        } else if (strcmp(node->name, "relay-password") == 0) {
318
            /* TODO: This is the backwards-compatibility location */
Michael Smith's avatar
Michael Smith committed
319 320
			if (configuration->relay_password && configuration->relay_password != CONFIG_DEFAULT_RELAY_PASSWORD) xmlFree(configuration->relay_password);
			configuration->relay_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
321 322
		} else if (strcmp(node->name, "icelogin") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Michael Smith's avatar
Michael Smith committed
323
			configuration->ice_login = atoi(tmp);
324
			if (tmp) xmlFree(tmp);
325 326
		} else if (strcmp(node->name, "fileserve") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Michael Smith's avatar
Michael Smith committed
327
			configuration->fileserve = atoi(tmp);
328
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
329
		} else if (strcmp(node->name, "hostname") == 0) {
Michael Smith's avatar
Michael Smith committed
330 331
			if (configuration->hostname && configuration->hostname != CONFIG_DEFAULT_HOSTNAME) xmlFree(configuration->hostname);
			configuration->hostname = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
332 333 334
		} else if (strcmp(node->name, "listen-socket") == 0) {
            _parse_listen_socket(doc, node->xmlChildrenNode, configuration);
        } else if (strcmp(node->name, "port") == 0) {
Jack Moffitt's avatar
Jack Moffitt committed
335
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
336 337
            configuration->port = atoi(tmp);
			configuration->listeners[0].port = atoi(tmp);
338
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
339
		} else if (strcmp(node->name, "bind-address") == 0) {
340 341 342
			if (configuration->listeners[0].bind_address) 
                xmlFree(configuration->listeners[0].bind_address);
			configuration->listeners[0].bind_address = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
343
		} else if (strcmp(node->name, "master-server") == 0) {
Michael Smith's avatar
Michael Smith committed
344 345
			if (configuration->master_server) xmlFree(configuration->master_server);
			configuration->master_server = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
346
		} else if (strcmp(node->name, "master-password") == 0) {
Michael Smith's avatar
Michael Smith committed
347 348
			if (configuration->master_password) xmlFree(configuration->master_password);
			configuration->master_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
349 350
		} else if (strcmp(node->name, "master-server-port") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Michael Smith's avatar
Michael Smith committed
351
			configuration->master_server_port = atoi(tmp);
352 353
        } else if (strcmp(node->name, "master-update-interval") == 0) {
            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Michael Smith's avatar
Michael Smith committed
354
            configuration->master_update_interval = atoi(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
355
		} else if (strcmp(node->name, "limits") == 0) {
Michael Smith's avatar
Michael Smith committed
356
			_parse_limits(doc, node->xmlChildrenNode, configuration);
Michael Smith's avatar
Michael Smith committed
357
		} else if (strcmp(node->name, "relay") == 0) {
Michael Smith's avatar
Michael Smith committed
358
			_parse_relay(doc, node->xmlChildrenNode, configuration);
359
		} else if (strcmp(node->name, "mount") == 0) {
Michael Smith's avatar
Michael Smith committed
360
			_parse_mount(doc, node->xmlChildrenNode, configuration);
Jack Moffitt's avatar
Jack Moffitt committed
361
		} else if (strcmp(node->name, "directory") == 0) {
Michael Smith's avatar
Michael Smith committed
362
			_parse_directory(doc, node->xmlChildrenNode, configuration);
Jack Moffitt's avatar
Jack Moffitt committed
363
		} else if (strcmp(node->name, "paths") == 0) {
Michael Smith's avatar
Michael Smith committed
364
			_parse_paths(doc, node->xmlChildrenNode, configuration);
Jack Moffitt's avatar
Jack Moffitt committed
365
		} else if (strcmp(node->name, "logging") == 0) {
Michael Smith's avatar
Michael Smith committed
366
			_parse_logging(doc, node->xmlChildrenNode, configuration);
367
        } else if (strcmp(node->name, "security") == 0) {
Michael Smith's avatar
Michael Smith committed
368
            _parse_security(doc, node->xmlChildrenNode, configuration);
Jack Moffitt's avatar
Jack Moffitt committed
369 370 371 372
		}
	} while ((node = node->next));
}

Michael Smith's avatar
Michael Smith committed
373 374
static void _parse_limits(xmlDocPtr doc, xmlNodePtr node, 
        ice_config_t *configuration)
Jack Moffitt's avatar
Jack Moffitt committed
375 376 377 378 379 380 381 382 383
{
	char *tmp;

	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "clients") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Michael Smith's avatar
Michael Smith committed
384
			configuration->client_limit = atoi(tmp);
385
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
386 387
		} else if (strcmp(node->name, "sources") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Michael Smith's avatar
Michael Smith committed
388
			configuration->source_limit = atoi(tmp);
389
			if (tmp) xmlFree(tmp);
390 391
		} else if (strcmp(node->name, "queue-size") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Michael Smith's avatar
Michael Smith committed
392
			configuration->queue_size_limit = atoi(tmp);
393
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
394 395
		} else if (strcmp(node->name, "threadpool") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Michael Smith's avatar
Michael Smith committed
396
			configuration->threadpool_size = atoi(tmp);
397
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
398 399
		} else if (strcmp(node->name, "client-timeout") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Michael Smith's avatar
Michael Smith committed
400
			configuration->client_timeout = atoi(tmp);
401
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
402 403
		} else if (strcmp(node->name, "header-timeout") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Michael Smith's avatar
Michael Smith committed
404
			configuration->header_timeout = atoi(tmp);
405
			if (tmp) xmlFree(tmp);
406 407
		} else if (strcmp(node->name, "source-timeout") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Michael Smith's avatar
Michael Smith committed
408
			configuration->source_timeout = atoi(tmp);
409
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
410 411 412 413
		}
	} while ((node = node->next));
}

Michael Smith's avatar
Michael Smith committed
414 415
static void _parse_mount(xmlDocPtr doc, xmlNodePtr node, 
        ice_config_t *configuration)
416 417 418
{
    char *tmp;
    mount_proxy *mount = calloc(1, sizeof(mount_proxy));
Michael Smith's avatar
Michael Smith committed
419
    mount_proxy *current = configuration->mounts;
420 421 422 423 424 425 426 427 428 429
    mount_proxy *last=NULL;
    
    while(current) {
        last = current;
        current = current->next;
    }

    if(last)
        last->next = mount;
    else
Michael Smith's avatar
Michael Smith committed
430
        configuration->mounts = mount;
431

432 433
    mount->max_listeners = -1;

434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "mount-name") == 0) {
            mount->mountname = (char *)xmlNodeListGetString(
                    doc, node->xmlChildrenNode, 1);
        }
        else if (strcmp(node->name, "username") == 0) {
            mount->username = (char *)xmlNodeListGetString(
                    doc, node->xmlChildrenNode, 1);
        }
        else if (strcmp(node->name, "password") == 0) {
            mount->password = (char *)xmlNodeListGetString(
                    doc, node->xmlChildrenNode, 1);
        }
        else if (strcmp(node->name, "dump-file") == 0) {
            mount->dumpfile = (char *)xmlNodeListGetString(
                    doc, node->xmlChildrenNode, 1);
        }
        else if (strcmp(node->name, "fallback-mount") == 0) {
            mount->fallback_mount = (char *)xmlNodeListGetString(
                    doc, node->xmlChildrenNode, 1);
        }
        else if (strcmp(node->name, "max-listeners") == 0) {
            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
            mount->max_listeners = atoi(tmp);
            if(tmp) xmlFree(tmp);
        }
	} while ((node = node->next));
}

Michael Smith's avatar
Michael Smith committed
466 467
static void _parse_relay(xmlDocPtr doc, xmlNodePtr node,
        ice_config_t *configuration)
Michael Smith's avatar
Michael Smith committed
468 469 470
{
    char *tmp;
    relay_server *relay = calloc(1, sizeof(relay_server));
Michael Smith's avatar
Michael Smith committed
471
    relay_server *current = configuration->relay;
Michael Smith's avatar
Michael Smith committed
472 473 474 475 476 477 478 479 480 481
    relay_server *last=NULL;
    
    while(current) {
        last = current;
        current = current->next;
    }

    if(last)
        last->next = relay;
    else
Michael Smith's avatar
Michael Smith committed
482
        configuration->relay = relay;
Michael Smith's avatar
Michael Smith committed
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500

	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "server") == 0) {
			relay->server = (char *)xmlNodeListGetString(
                    doc, node->xmlChildrenNode, 1);
        }
        else if (strcmp(node->name, "port") == 0) {
            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
            relay->port = atoi(tmp);
            if(tmp) xmlFree(tmp);
        }
        else if (strcmp(node->name, "mount") == 0) {
			relay->mount = (char *)xmlNodeListGetString(
                    doc, node->xmlChildrenNode, 1);
        }
501 502 503 504
        else if (strcmp(node->name, "local-mount") == 0) {
			relay->localmount = (char *)xmlNodeListGetString(
                    doc, node->xmlChildrenNode, 1);
        }
505 506 507 508 509
        else if (strcmp(node->name, "relay-shoutcast-metadata") == 0) {
            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
            relay->mp3metadata = atoi(tmp);
            if(tmp) xmlFree(tmp);
        }
Michael Smith's avatar
Michael Smith committed
510 511 512
	} while ((node = node->next));
}

513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
static void _parse_listen_socket(xmlDocPtr doc, xmlNodePtr node,
        ice_config_t *configuration)
{
    listener_t *listener = NULL;
    int i;
    char *tmp;

    for(i=0; i < MAX_LISTEN_SOCKETS; i++) {
        if(configuration->listeners[i].port <= 0) {
            listener = &(configuration->listeners[i]);
            break;
        }
    }

	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "port") == 0) {
            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
            if(configuration->port == 0)
                configuration->port = atoi(tmp);
            listener->port = atoi(tmp);
            if(tmp) xmlFree(tmp);
        }
        else if (strcmp(node->name, "bind-address") == 0) {
            listener->bind_address = (char *)xmlNodeListGetString(doc, 
                    node->xmlChildrenNode, 1);
        }
	} while ((node = node->next));
}

Michael Smith's avatar
Michael Smith committed
545 546
static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node,
        ice_config_t *configuration)
547 548 549 550 551 552 553 554 555 556 557 558
{
	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "source-password") == 0) {
            char *mount, *pass;
            if ((mount = (char *)xmlGetProp(node, "mount")) != NULL) {
                pass = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
                /* FIXME: This is a placeholder for per-mount passwords */
            }
            else {
Michael Smith's avatar
Michael Smith committed
559 560
			    if (configuration->source_password && 
                        configuration->source_password != 
561
                        CONFIG_DEFAULT_SOURCE_PASSWORD) 
Michael Smith's avatar
Michael Smith committed
562 563
                    xmlFree(configuration->source_password);
			    configuration->source_password = 
564 565 566
                    (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
            }
        } else if (strcmp(node->name, "relay-password") == 0) {
Michael Smith's avatar
Michael Smith committed
567 568
			if (configuration->relay_password && 
                    configuration->relay_password != 
569
                    CONFIG_DEFAULT_RELAY_PASSWORD) 
Michael Smith's avatar
Michael Smith committed
570 571
                xmlFree(configuration->relay_password);
			configuration->relay_password = 
572 573
                (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
		} else if (strcmp(node->name, "admin-password") == 0) {
Michael Smith's avatar
Michael Smith committed
574 575 576
            if(configuration->admin_password)
                xmlFree(configuration->admin_password);
            configuration->admin_password =
577 578
                (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
		} else if (strcmp(node->name, "admin-user") == 0) {
Michael Smith's avatar
Michael Smith committed
579 580 581
            if(configuration->admin_username)
                xmlFree(configuration->admin_username);
            configuration->admin_username =
582 583 584 585 586
                (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
        }
	} while ((node = node->next));
}

Michael Smith's avatar
Michael Smith committed
587 588
static void _parse_directory(xmlDocPtr doc, xmlNodePtr node,
        ice_config_t *configuration)
Jack Moffitt's avatar
Jack Moffitt committed
589 590 591
{
	char *tmp;

Michael Smith's avatar
Michael Smith committed
592
	if (configuration->num_yp_directories >= MAX_YP_DIRECTORIES) {
593 594 595
		ERROR0("Maximum number of yp directories exceeded!");
		return;
	}
Jack Moffitt's avatar
Jack Moffitt committed
596 597 598 599
	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

600
		if (strcmp(node->name, "yp-url") == 0) {
Michael Smith's avatar
Michael Smith committed
601 602 603
			if (configuration->yp_url[configuration->num_yp_directories]) 
                xmlFree(configuration->yp_url[configuration->num_yp_directories]);
			configuration->yp_url[configuration->num_yp_directories] = 
604
                (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
605 606
        } else if (strcmp(node->name, "yp-url-timeout") == 0) {
            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Michael Smith's avatar
Michael Smith committed
607
            configuration->yp_url_timeout[configuration->num_yp_directories] = 
608
                atoi(tmp);
609
		} else if (strcmp(node->name, "server") == 0) {
Michael Smith's avatar
Michael Smith committed
610
			_add_server(doc, node->xmlChildrenNode, configuration);
611
		} else if (strcmp(node->name, "touch-interval") == 0) {
Jack Moffitt's avatar
Jack Moffitt committed
612
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Michael Smith's avatar
Michael Smith committed
613
			configuration->touch_interval = atoi(tmp);
614
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
615 616
		}
	} while ((node = node->next));
Michael Smith's avatar
Michael Smith committed
617
	configuration->num_yp_directories++;
Jack Moffitt's avatar
Jack Moffitt committed
618 619
}

Michael Smith's avatar
Michael Smith committed
620 621
static void _parse_paths(xmlDocPtr doc, xmlNodePtr node,
        ice_config_t *configuration)
Jack Moffitt's avatar
Jack Moffitt committed
622 623 624 625 626 627
{
	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "basedir") == 0) {
Michael Smith's avatar
Michael Smith committed
628 629
			if (configuration->base_dir && configuration->base_dir != CONFIG_DEFAULT_BASE_DIR) xmlFree(configuration->base_dir);
			configuration->base_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Jack Moffitt's avatar
Jack Moffitt committed
630
		} else if (strcmp(node->name, "logdir") == 0) {
Michael Smith's avatar
Michael Smith committed
631 632
			if (configuration->log_dir && configuration->log_dir != CONFIG_DEFAULT_LOG_DIR) xmlFree(configuration->log_dir);
			configuration->log_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
633
		} else if (strcmp(node->name, "webroot") == 0) {
Michael Smith's avatar
Michael Smith committed
634 635 636 637
			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;
638

Jack Moffitt's avatar
Jack Moffitt committed
639 640 641 642
		}
	} while ((node = node->next));
}

Michael Smith's avatar
Michael Smith committed
643 644
static void _parse_logging(xmlDocPtr doc, xmlNodePtr node,
        ice_config_t *configuration)
Jack Moffitt's avatar
Jack Moffitt committed
645 646 647 648 649 650
{
	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "accesslog") == 0) {
Michael Smith's avatar
Michael Smith committed
651 652
			if (configuration->access_log && configuration->access_log != CONFIG_DEFAULT_ACCESS_LOG) xmlFree(configuration->access_log);
			configuration->access_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Jack Moffitt's avatar
Jack Moffitt committed
653
		} else if (strcmp(node->name, "errorlog") == 0) {
Michael Smith's avatar
Michael Smith committed
654 655
			if (configuration->error_log && configuration->error_log != CONFIG_DEFAULT_ERROR_LOG) xmlFree(configuration->error_log);
			configuration->error_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
656 657
		} else if (strcmp(node->name, "loglevel") == 0) {
           char *tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Michael Smith's avatar
Michael Smith committed
658
           configuration->loglevel = atoi(tmp);
659
           if (tmp) xmlFree(tmp);
660
        }
Jack Moffitt's avatar
Jack Moffitt committed
661 662 663
	} while ((node = node->next));
}

Michael Smith's avatar
Michael Smith committed
664 665
static void _parse_security(xmlDocPtr doc, xmlNodePtr node,
        ice_config_t *configuration)
666 667 668 669 670 671 672 673 674 675
{
   char *tmp;
   xmlNodePtr oldnode;

   do {
       if (node == NULL) break;
       if (xmlIsBlankNode(node)) continue;

       if (strcmp(node->name, "chroot") == 0) {
           tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Michael Smith's avatar
Michael Smith committed
676
           configuration->chroot = atoi(tmp);
677
           if (tmp) xmlFree(tmp);
678
       } else if (strcmp(node->name, "changeowner") == 0) {
Michael Smith's avatar
Michael Smith committed
679
           configuration->chuid = 1;
680 681 682 683 684 685
           oldnode = node;
           node = node->xmlChildrenNode;
           do {
               if(node == NULL) break;
               if(xmlIsBlankNode(node)) continue;
               if(strcmp(node->name, "user") == 0) {
Michael Smith's avatar
Michael Smith committed
686 687
                   if(configuration->user) xmlFree(configuration->user);
                   configuration->user = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
688
               } else if(strcmp(node->name, "group") == 0) {
Michael Smith's avatar
Michael Smith committed
689 690
                   if(configuration->group) xmlFree(configuration->group);
                   configuration->group = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
691 692 693 694 695 696 697
               }
           } while((node = node->next));
           node = oldnode;
       }
   } while ((node = node->next));
}

Michael Smith's avatar
Michael Smith committed
698 699
static void _add_server(xmlDocPtr doc, xmlNodePtr node, 
        ice_config_t *configuration)
Jack Moffitt's avatar
Jack Moffitt committed
700 701 702 703 704 705
{
	ice_config_dir_t *dirnode, *server;
	int addnode;
	char *tmp;

	server = (ice_config_dir_t *)malloc(sizeof(ice_config_dir_t));
Michael Smith's avatar
Michael Smith committed
706
	server->touch_interval = configuration->touch_interval;
Jack Moffitt's avatar
Jack Moffitt committed
707 708 709 710 711 712 713 714
	server->host = NULL;
	addnode = 0;
	
	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "host") == 0) {
715 716
			server->host = (char *)xmlNodeListGetString(doc, 
                    node->xmlChildrenNode, 1);
Jack Moffitt's avatar
Jack Moffitt committed
717
			addnode = 1;
718
		} else if (strcmp(node->name, "touch-interval") == 0) {
Jack Moffitt's avatar
Jack Moffitt committed
719
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
720
			server->touch_interval = atoi(tmp);
721
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
722 723 724 725 726
		}
		server->next = NULL;
	} while ((node = node->next));

	if (addnode) {
Michael Smith's avatar
Michael Smith committed
727
		dirnode = configuration->dir_list;
Jack Moffitt's avatar
Jack Moffitt committed
728
		if (dirnode == NULL) {
Michael Smith's avatar
Michael Smith committed
729
			configuration->dir_list = server;
Jack Moffitt's avatar
Jack Moffitt committed
730 731 732 733 734 735 736 737 738 739 740 741 742
		} else {
			while (dirnode->next) dirnode = dirnode->next;
			
			dirnode->next = server;
		}
		
		server = NULL;
		addnode = 0;
	}
	
}