Bug in handling fallback-override clients + patch

Mart van Santen <[email protected]>
Newsgroups gmane.comp.audio.icecast.devel
Message-ID <[email protected]>
Hello,

I noticed a bug in the fallback-override handling in icecast 2.3.3. The
bug is as follows:

We use icecast for distributing a continuous radio stream, let's call
this stream "live", with mountpoint "/live"

In our usecase we have a second audio stream, called "event". This
stream is only online when there is a special event. This is on
mountpoint "/event".

Because we want the "event" stream also to be available, also when there
is no event, we've defined an fallback for the 'event' stream to 'live',
as follows:

    <mount>
        <mount-name>/event</mount-name>
        <fallback-mount>/live</fallback-mount>
        <fallback-override>1</fallback-override>
    </mount>

The expected behavior, when a user is listening to /event, it will
stream /live, and once the event stream is up, the user will be moved to
the special 'event' stream.

This is working fine.

The problem is, icecast is moving 'all' users on '/live' to '/event',
once the event stream get's up.
Also the users who started on '/live' and not to the special '/event'
stream.

The bug is that icecast should not move back users who started on the
'/live' stream, but only users who started listing to the '/event' stream.

I've attached a patch to this e-mail to solve this bug. Unforunally my C
is not very well developed, so I hope I didn't make any pointer or
buffer-overflow errors.

They idea is to store the original requested mountpoint in the client's
structure. Once a fallback-override happens, we check with a strcmp if
the client should be moved back. If not, we leave the client on the
current stream.

I tested this code for correct behavior with 6 clients on two streams.
This works all fine, with starting/stopping the source stream "event"
and opening/closing streams.

I hope you can patch this upstream as well.


Kind regards,

Mart van Santen







-- 
Mart van Santen
Greenhost
E: [email protected]
T: +31204890444
A: Weesperstraat 3, Amsterdam, Netherlands

A PGP signature can be attached to this e-mail,
you need PGP software to verify it.
My public key is available in keyserver(s)
see: http://tinyurl.com/openpgp-manual

PGP Fingerprint: CA85 EB11 2B70 042D AF66  B29A 6437 01A1 10A3 D3A5

_______________________________________________
Icecast-dev mailing list
[email protected]
http://lists.xiph.org/mailman/listinfo/icecast-dev
fallback-override-org-stream-only.patch (text/x-patch, 6.4 KB)
diff -u -r icecast-2.3.3.org/src/admin.c icecast-2.3.3/src/admin.c
--- icecast-2.3.3.org/src/admin.c	2012-06-11 18:45:20.000000000 +0200
+++ icecast-2.3.3/src/admin.c	2013-06-14 06:54:16.046904972 +0200
@@ -622,7 +622,7 @@
     node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL);
     xmlDocSetRootElement(doc, node);
 
-    source_move_clients (source, dest);
+    source_move_clients (source, dest, 0);
 
     memset(buf, '\000', sizeof(buf));
     snprintf (buf, sizeof(buf), "Clients moved from %s to %s",
diff -u -r icecast-2.3.3.org/src/auth.c icecast-2.3.3/src/auth.c
--- icecast-2.3.3.org/src/auth.c	2012-06-11 18:45:20.000000000 +0200
+++ icecast-2.3.3/src/auth.c	2013-06-14 11:24:45.448146436 +0200
@@ -447,6 +449,10 @@
         return 0;
     }
 
+    /* Save requested mountpoint in client pointer. We use this to know how 
+       to handle failover-override to back users back to original 
+       audiostream */
+    client->mountpoint = strdup (mount);
     avl_tree_rlock (global.source_tree);
     source = source_find_mount (mount);
 
diff -u -r icecast-2.3.3.org/src/client.h icecast-2.3.3/src/client.h
--- icecast-2.3.3.org/src/client.h	2012-06-11 18:45:20.000000000 +0200
+++ icecast-2.3.3/src/client.h	2013-06-14 06:46:24.863767986 +0200
@@ -47,6 +47,9 @@
     /* auth used for this client */
     struct auth_tag *auth;
 
+    /* Client's original mountpoint */
+    char *mountpoint;
+
     /* Client username, if authenticated */
     char *username;
 
diff -u -r icecast-2.3.3.org/src/slave.c icecast-2.3.3/src/slave.c
--- icecast-2.3.3.org/src/slave.c	2012-06-11 18:45:20.000000000 +0200
+++ icecast-2.3.3/src/slave.c	2013-06-14 06:54:29.731000202 +0200
@@ -361,7 +361,7 @@
         fallback_source = source_find_mount (relay->source->fallback_mount);
 
         if (fallback_source != NULL)
-            source_move_clients (relay->source, fallback_source);
+            source_move_clients (relay->source, fallback_source,0);
 
         avl_tree_unlock (global.source_tree);
     }
diff -u -r icecast-2.3.3.org/src/source.c icecast-2.3.3/src/source.c
--- icecast-2.3.3.org/src/source.c	2012-06-11 18:45:20.000000000 +0200
+++ icecast-2.3.3/src/source.c	2013-06-14 10:24:12.922495076 +0200
@@ -338,7 +338,7 @@
  * 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)
+void source_move_clients (source_t *source, source_t *dest, int override)
 {
     unsigned long count = 0;
     if (strcmp (source->mount, dest->mount) == 0)
@@ -382,13 +382,38 @@
                 break;
             }
         }
-
+	
         while (1)
         {
+            /*  Get first node in tree */
             avl_node *node = avl_get_first (source->pending_tree);
             if (node == NULL)
                 break;
             client = (client_t *)(node->key);
+
+
+	    /* override flag: set when return to original source getting back */
+	    if (override == 1) {
+
+	        /* check original mountpoint */
+		while (strcmp(client->mountpoint, dest->mount) != 0) {
+			WARN2("client came not form this source, so not moving (client mountpoint: %s and fallback mountmout: %s)", client->mountpoint, dest->mount);
+	                /* get next node */
+			node = avl_get_next(node);
+                
+			if (node == NULL)
+		        	break;
+
+                        client = (client_t *)(node->key);
+		}
+  	    }
+
+            
+            if (node == NULL)
+                break;
+
+
+
             avl_delete (source->pending_tree, client, NULL);
 
             /* when switching a client to a different queue, be wary of the 
@@ -402,7 +427,6 @@
                 if (source->con == NULL)
                     client->intro_offset = -1;
             }
-
             avl_insert (dest->pending_tree, (void *)client);
             count++;
         }
@@ -412,8 +436,28 @@
             avl_node *node = avl_get_first (source->client_tree);
             if (node == NULL)
                 break;
-
             client = (client_t *)(node->key);
+
+	    /* override flag: set when return to original source getting back */
+	    if (override == 1) {
+
+	        /* check original mountpoint */
+		while (strcmp(client->mountpoint, dest->mount) != 0) {
+			WARN2("client came not form this source, so not moving (client mountpoint: %s and fallback mountmout: %s)", client->mountpoint, dest->mount);
+	                /* get next node */
+			node = avl_get_next(node);
+                
+			if (node == NULL)
+		        	break;
+
+                        client = (client_t *)(node->key);
+		}
+  	    }
+
+            
+            if (node == NULL)
+                break;
+
             avl_delete (source->client_tree, client, NULL);
 
             /* when switching a client to a different queue, be wary of the 
@@ -427,12 +471,13 @@
                 if (source->con == NULL)
                     client->intro_offset = -1;
             }
+
             avl_insert (dest->pending_tree, (void *)client);
             count++;
         }
         INFO2 ("passing %lu listeners to \"%s\"", count, dest->mount);
 
-        source->listeners = 0;
+        source->listeners = source->listeners - count;
         stats_event (source->mount, "listeners", "0");
 
     } while (0);
@@ -659,7 +704,7 @@
         fallback_source = source_find_mount(source->fallback_mount);
 
         if (fallback_source)
-            source_move_clients (fallback_source, source);
+            source_move_clients (fallback_source, source, 1);
 
         avl_tree_unlock(global.source_tree);
     }
@@ -861,7 +906,7 @@
         fallback_source = source_find_mount (source->fallback_mount);
 
         if (fallback_source != NULL)
-            source_move_clients (source, fallback_source);
+            source_move_clients (source, fallback_source, 0);
 
         avl_tree_unlock (global.source_tree);
     }
diff -u -r icecast-2.3.3.org/src/source.h icecast-2.3.3/src/source.h
--- icecast-2.3.3.org/src/source.h	2012-06-11 18:45:20.000000000 +0200
+++ icecast-2.3.3/src/source.h	2013-06-14 06:55:04.363238171 +0200
@@ -89,7 +89,7 @@
 client_t *source_find_client(source_t *source, int 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);
+void source_move_clients (source_t *source, source_t *dest, int override);
 int source_remove_client(void *key);
 void source_main(source_t *source);
 void source_recheck_mounts (int update_all);
signature.asc (application/pgp-signature, 555 B)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQEcBAEBAgAGBQJRuu2mAAoJEGQ3AaEQo9Ol2msH/1u+jO00ArHT01YbNar3fu/n
JSbqYSLqdoIYQfZhrYEugQqQJvFqWwc+NgTtTdDUur12yFPW48OweIeQbENinsK0
XpS+A+nHGNeEVW+oBnT7p6R22w8JyOmcxLmvDuyhai+YPs+8aKjvAWEacxzw9wDn
lRgw/ko2RHnkzOUEFs3nlnVb4O60Kc8/2Lwt6y/tAFcqCuhzHzfk5iiAOMfit9Vy
Zug20Ps7FWOQyZ548MzQsH2mszLvBW4laekNguSj9iDEtQHjGRkUvK6xWLMhIP0+
Is84OKDJGKDttYRJAdmX74bJAyPGLY0rD2CDttJT2Fmw4BkCg7GliXcX2+hgeqY=
=aUoT
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.