mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-12-04 14:46:30 -05:00
Feature: Correctly navigate clients between mounts
This commit is contained in:
parent
5c504ec3dd
commit
8a91113028
@ -936,6 +936,9 @@ static void __add_listener_to_source(source_t *source, client_t *client)
|
||||
{
|
||||
size_t loop = 10;
|
||||
|
||||
if (navigation_history_navigate_to(&(client->history), source->identifier, NAVIGATION_DIRECTION_REPLACE_ALL) != 0)
|
||||
ICECAST_LOG_ERROR("Can not change history: navigation of client=%p{.con.id=%llu, ...} to source=%p{.mount=%#H, ...} failed", client, (unsigned long long int)client->con->id, source, source->mount);
|
||||
|
||||
do {
|
||||
ICECAST_LOG_DEBUG("max on %s is %ld (cur %lu)", source->mount,
|
||||
source->max_listeners, source->listeners);
|
||||
@ -954,6 +957,7 @@ static void __add_listener_to_source(source_t *source, client_t *client)
|
||||
}
|
||||
ICECAST_LOG_INFO("stream full, trying %s", next->mount);
|
||||
source = next;
|
||||
navigation_history_navigate_to(&(client->history), source->identifier, NAVIGATION_DIRECTION_DOWN);
|
||||
loop--;
|
||||
continue;
|
||||
}
|
||||
@ -967,9 +971,6 @@ static void __add_listener_to_source(source_t *source, client_t *client)
|
||||
client->refbuf->len = PER_CLIENT_REFBUF_SIZE;
|
||||
memset(client->refbuf->data, 0, PER_CLIENT_REFBUF_SIZE);
|
||||
|
||||
if (navigation_history_navigate_to(&(client->history), source->identifier, NAVIGATION_DIRECTION_REPLACE_ALL) != 0)
|
||||
ICECAST_LOG_ERROR("Can not change history: navigation of client=%p{.con.id=%llu, ...} to source=%p{.mount=%#H, ...} failed", client, (unsigned long long int)client->con->id, source, source->mount);
|
||||
|
||||
/* lets add the client to the active list */
|
||||
avl_tree_wlock(source->pending_tree);
|
||||
avl_insert(source->pending_tree, client);
|
||||
|
@ -90,6 +90,9 @@ static inline int navigation_history_pop(navigation_history_t *history)
|
||||
|
||||
static inline int navigation_history_push(navigation_history_t *history, mount_identifier_t *identifier)
|
||||
{
|
||||
if (history->fill > 0 && mount_identifier_compare(history->history[history->fill - 1], identifier) == 0)
|
||||
return 0;
|
||||
|
||||
if (refobject_ref(identifier) != 0)
|
||||
return -1;
|
||||
|
||||
@ -132,6 +135,9 @@ int navigation_history_navigate_to(navigation_history_t *his
|
||||
if (!history || !identifier)
|
||||
return -1;
|
||||
|
||||
if (direction == NAVIGATION_DIRECTION_UP && history->fill < 2)
|
||||
direction = NAVIGATION_DIRECTION_REPLACE_ALL;
|
||||
|
||||
switch (direction) {
|
||||
case NAVIGATION_DIRECTION_UP:
|
||||
if (history->fill < 2)
|
||||
@ -147,6 +153,10 @@ int navigation_history_navigate_to(navigation_history_t *his
|
||||
if (history->fill == 0) {
|
||||
return navigation_history_push(history, identifier);
|
||||
} else {
|
||||
if (history->fill > 1 && mount_identifier_compare(history->history[history->fill - 2], identifier) == 0) {
|
||||
return navigation_history_pop(history);
|
||||
}
|
||||
|
||||
if (refobject_ref(identifier) != 0)
|
||||
return -1;
|
||||
refobject_unref(history->history[history->fill - 1]);
|
||||
|
@ -469,7 +469,7 @@ static void *start_relay_stream (void *arg)
|
||||
fallback_source = source_find_mount(relay->source->fallback_mount);
|
||||
|
||||
if (fallback_source != NULL)
|
||||
source_move_clients(relay->source, fallback_source, NULL);
|
||||
source_move_clients(relay->source, fallback_source, NULL, NAVIGATION_DIRECTION_DOWN);
|
||||
|
||||
avl_tree_unlock(global.source_tree);
|
||||
}
|
||||
|
15
src/source.c
15
src/source.c
@ -345,7 +345,7 @@ client_t *source_find_client(source_t *source, connection_id_t id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void source_move_clients__single(source_t *source, avl_tree *from, avl_tree *to, client_t *client) {
|
||||
static inline void source_move_clients__single(source_t *source, source_t *dest, avl_tree *from, avl_tree *to, client_t *client, navigation_direction_t direction) {
|
||||
avl_delete(from, client, NULL);
|
||||
|
||||
/* when switching a client to a different queue, be wary of the
|
||||
@ -360,6 +360,7 @@ static inline void source_move_clients__single(source_t *source, avl_tree *from,
|
||||
}
|
||||
|
||||
avl_insert(to, (void *)client);
|
||||
navigation_history_navigate_to(&(client->history), dest->identifier, direction);
|
||||
}
|
||||
|
||||
/* Move clients from source to dest provided dest is running
|
||||
@ -367,7 +368,7 @@ static inline void source_move_clients__single(source_t *source, avl_tree *from,
|
||||
* The only lock that should be held when this is called is the
|
||||
* source tree lock
|
||||
*/
|
||||
void source_move_clients(source_t *source, source_t *dest, connection_id_t *id)
|
||||
void source_move_clients(source_t *source, source_t *dest, connection_id_t *id, navigation_direction_t direction)
|
||||
{
|
||||
unsigned long count = 0;
|
||||
if (strcmp(source->mount, dest->mount) == 0) {
|
||||
@ -414,7 +415,7 @@ void source_move_clients(source_t *source, source_t *dest, connection_id_t *id)
|
||||
fakeclient.con->id = *id;
|
||||
|
||||
if (avl_get_by_key(source->client_tree, &fakeclient, &result) == 0) {
|
||||
source_move_clients__single(source, source->client_tree, dest->pending_tree, result);
|
||||
source_move_clients__single(source, dest, source->client_tree, dest->pending_tree, result, direction);
|
||||
count++;
|
||||
}
|
||||
} else {
|
||||
@ -422,7 +423,7 @@ void source_move_clients(source_t *source, source_t *dest, connection_id_t *id)
|
||||
avl_node *node = avl_get_first(source->pending_tree);
|
||||
if (node == NULL)
|
||||
break;
|
||||
source_move_clients__single(source, source->pending_tree, dest->pending_tree, node->key);
|
||||
source_move_clients__single(source, dest, source->pending_tree, dest->pending_tree, node->key, direction);
|
||||
count++;
|
||||
}
|
||||
|
||||
@ -430,7 +431,7 @@ void source_move_clients(source_t *source, source_t *dest, connection_id_t *id)
|
||||
avl_node *node = avl_get_first(source->client_tree);
|
||||
if (node == NULL)
|
||||
break;
|
||||
source_move_clients__single(source, source->client_tree, dest->pending_tree, node->key);
|
||||
source_move_clients__single(source, dest, source->client_tree, dest->pending_tree, node->key, direction);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@ -667,7 +668,7 @@ static void source_init (source_t *source)
|
||||
fallback_source = source_find_mount(source->fallback_mount);
|
||||
|
||||
if (fallback_source)
|
||||
source_move_clients(fallback_source, source, NULL);
|
||||
source_move_clients(fallback_source, source, NULL, NAVIGATION_DIRECTION_UP);
|
||||
|
||||
avl_tree_unlock(global.source_tree);
|
||||
}
|
||||
@ -866,7 +867,7 @@ static void source_shutdown (source_t *source)
|
||||
fallback_source = source_find_mount(source->fallback_mount);
|
||||
|
||||
if (fallback_source != NULL)
|
||||
source_move_clients(source, fallback_source, NULL);
|
||||
source_move_clients(source, fallback_source, NULL, NAVIGATION_DIRECTION_DOWN);
|
||||
|
||||
avl_tree_unlock(global.source_tree);
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ source_t *source_find_mount_raw(const char *mount);
|
||||
client_t *source_find_client(source_t *source, connection_id_t id);
|
||||
int source_compare_sources(void *arg, void *a, void *b);
|
||||
void source_free_source(source_t *source);
|
||||
void source_move_clients(source_t *source, source_t *dest, connection_id_t *id);
|
||||
void source_move_clients(source_t *source, source_t *dest, connection_id_t *id, navigation_direction_t direction);
|
||||
int source_remove_client(void *key);
|
||||
void source_main(source_t *source);
|
||||
void source_recheck_mounts (int update_all);
|
||||
|
Loading…
Reference in New Issue
Block a user