mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-12-04 14:46:30 -05:00
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
This commit is contained in:
parent
8f0aefb2be
commit
76fc62810e
@ -290,6 +290,9 @@ static connection_t *_get_connection(void)
|
|||||||
return con;
|
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) {
|
int connection_create_source(client_t *client, connection_t *con, http_parser_t *parser, char *mount) {
|
||||||
source_t *source;
|
source_t *source;
|
||||||
char *contenttype;
|
char *contenttype;
|
||||||
@ -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.");
|
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);
|
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;
|
client->respcode = 200;
|
||||||
bytes = sock_write(client->con->sock,
|
bytes = sock_write(client->con->sock,
|
||||||
"HTTP/1.0 200 OK\r\n\r\n");
|
"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);
|
avl_tree_rlock(global.source_tree);
|
||||||
if (source_find_mount(uri) != NULL) {
|
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);
|
INFO1("Source tried to log in as %s, but mountpoint is already used", uri);
|
||||||
client_send_404(client, "Mountpoint in use");
|
client_send_404(client, "Mountpoint in use");
|
||||||
avl_tree_unlock(global.source_tree);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
avl_tree_unlock(global.source_tree);
|
avl_tree_unlock(global.source_tree);
|
||||||
|
|
||||||
if (!connection_create_source(client, con, parser, uri)) {
|
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;
|
relay = config_get_config()->relay;
|
||||||
while(relay) {
|
while(relay) {
|
||||||
avl_tree_rlock(global.source_tree);
|
avl_tree_rlock(global.source_tree);
|
||||||
if(!source_find_mount(relay->mount)) {
|
if(!source_find_mount(relay->localmount)) {
|
||||||
avl_tree_unlock(global.source_tree);
|
avl_tree_unlock(global.source_tree);
|
||||||
|
|
||||||
create_relay_stream(relay->server, relay->port, relay->mount,
|
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->client = client;
|
||||||
src->mount = (char *)strdup(mount);
|
src->mount = (char *)strdup(mount);
|
||||||
src->fallback_mount = NULL;
|
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->con = con;
|
||||||
src->parser = parser;
|
src->parser = parser;
|
||||||
src->client_tree = avl_tree_new(_compare_clients, NULL);
|
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)
|
void *source_main(void *arg)
|
||||||
{
|
{
|
||||||
source_t *source = (source_t *)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 */
|
/* 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);
|
||||||
|
|
||||||
/* get a write lock on the global source tree */
|
/* The caller has ensured we have a write lock on the tree... */
|
||||||
avl_tree_wlock(global.source_tree);
|
|
||||||
/* insert source onto source tree */
|
/* insert source onto source tree */
|
||||||
avl_insert(global.source_tree, (void *)source);
|
avl_insert(global.source_tree, (void *)source);
|
||||||
/* release write lock on global source tree */
|
/* release write lock on global source tree */
|
||||||
|
Loading…
Reference in New Issue
Block a user