Commit 76fc6281 authored by Michael Smith's avatar Michael Smith

Fix a serious bug with source creation in relays when local-mount != mount,

and fix a series of locking bugs in source creation.

svn path=/trunk/icecast/; revision=4352
parent 8f0aefb2
......@@ -290,6 +290,9 @@ static connection_t *_get_connection(void)
return con;
}
/* TODO: Make this return an appropriate error code so that we can use HTTP
* codes where appropriate
*/
int connection_create_source(client_t *client, connection_t *con, http_parser_t *parser, char *mount) {
source_t *source;
char *contenttype;
......@@ -306,7 +309,7 @@ int connection_create_source(client_t *client, connection_t *con, http_parser_t
}
global.sources++;
global_unlock();
stats_event_inc(NULL, "sources");
contenttype = httpp_getvar(parser, "content-type");
......@@ -324,6 +327,21 @@ int connection_create_source(client_t *client, connection_t *con, http_parser_t
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);
}
/* We did a preliminary check earlier, to catch the common case before
* we do any unneccesary processing. Now, we do a check that must be
* correct - so we have to take a write lock out, since we need to
* add this source if it doesn't already exist.
*/
avl_tree_wlock(global.source_tree);
if (source_find_mount(mount) != NULL) {
INFO1("Source tried to log in as %s, but mountpoint is already used",
mount);
avl_tree_unlock(global.source_tree);
goto fail;
}
/* Keep the tree locked - it gets unlocked in source_main */
client->respcode = 200;
bytes = sock_write(client->con->sock,
"HTTP/1.0 200 OK\r\n\r\n");
......@@ -569,15 +587,15 @@ static void _handle_source_request(connection_t *con,
avl_tree_rlock(global.source_tree);
if (source_find_mount(uri) != NULL) {
avl_tree_unlock(global.source_tree);
INFO1("Source tried to log in as %s, but mountpoint is already used", uri);
client_send_404(client, "Mountpoint in use");
avl_tree_unlock(global.source_tree);
return;
}
avl_tree_unlock(global.source_tree);
if (!connection_create_source(client, con, parser, uri)) {
client_destroy(client);
client_send_404(client, "Mountpoint in use");
}
}
......
......@@ -180,7 +180,7 @@ static void *_slave_thread(void *arg) {
relay = config_get_config()->relay;
while(relay) {
avl_tree_rlock(global.source_tree);
if(!source_find_mount(relay->mount)) {
if(!source_find_mount(relay->localmount)) {
avl_tree_unlock(global.source_tree);
create_relay_stream(relay->server, relay->port, relay->mount,
......
......@@ -48,7 +48,7 @@ source_t *source_create(client_t *client, connection_t *con, http_parser_t *pars
src->client = client;
src->mount = (char *)strdup(mount);
src->fallback_mount = NULL;
src->format = format_get_plugin(type, src->mount);
src->format = format_get_plugin(type, src->mount, parser);
src->con = con;
src->parser = parser;
src->client_tree = avl_tree_new(_compare_clients, NULL);
......@@ -129,6 +129,9 @@ int source_free_source(void *key)
}
/* The caller MUST have a current write lock on global.source_tree when calling
* this
*/
void *source_main(void *arg)
{
source_t *source = (source_t *)arg;
......@@ -154,8 +157,8 @@ void *source_main(void *arg)
/* grab a read lock, to make sure we get a chance to cleanup */
thread_rwlock_rlock(source->shutdown_rwlock);
/* get a write lock on the global source tree */
avl_tree_wlock(global.source_tree);
/* The caller has ensured we have a write lock on the tree... */
/* insert source onto source tree */
avl_insert(global.source_tree, (void *)source);
/* release write lock on global source tree */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment