[xiph-commits] r10828 - in icecast/branches/kh/icecast: . admin conf doc src

karl at svn.xiph.org karl at svn.xiph.org
Thu Feb 16 16:42:15 PST 2006


Author: karl
Date: 2006-02-16 16:42:03 -0800 (Thu, 16 Feb 2006)
New Revision: 10828

Modified:
   icecast/branches/kh/icecast/NEWS
   icecast/branches/kh/icecast/admin/stats.xsl
   icecast/branches/kh/icecast/conf/icecast.xml.in
   icecast/branches/kh/icecast/configure.in
   icecast/branches/kh/icecast/doc/icecast2_listenerauth.html
   icecast/branches/kh/icecast/doc/icecast2_relay.html
   icecast/branches/kh/icecast/src/admin.c
   icecast/branches/kh/icecast/src/auth.c
   icecast/branches/kh/icecast/src/auth_url.c
   icecast/branches/kh/icecast/src/cfgfile.c
   icecast/branches/kh/icecast/src/cfgfile.h
   icecast/branches/kh/icecast/src/client.c
   icecast/branches/kh/icecast/src/client.h
   icecast/branches/kh/icecast/src/connection.c
   icecast/branches/kh/icecast/src/format.c
   icecast/branches/kh/icecast/src/global.h
   icecast/branches/kh/icecast/src/slave.c
   icecast/branches/kh/icecast/src/slave.h
   icecast/branches/kh/icecast/src/source.c
   icecast/branches/kh/icecast/src/yp.c
Log:
bump version. mainly an update of 302 work, other bits missed out from before


Modified: icecast/branches/kh/icecast/NEWS
===================================================================
--- icecast/branches/kh/icecast/NEWS	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/NEWS	2006-02-17 00:42:03 UTC (rev 10828)
@@ -9,9 +9,33 @@
 TODO
 . update slave host handling to add entry via url, as on-demand relays don't
   connect until there are listeners.
-. get feedback from people on listener auth via url, Stephen Nixon has done
-  some auth scripts that people can use at http://imux.net/icecast/
 
+2.3-kh3
+. add source auth via authenticator, affects certain admin access as well.
+  Only url auth using it currently
+. relays now have start timestamps, prevents a possible constant rescanning
+  effect with multiple relay failure case
+. fix memory leak in ogg flac case.
+. update YP, get bitrate from stats (incoming_bitrate), if not provided. Issue
+  yp add after 60 secs, gives time for bitrates to settle.
+. cleanups in auth setup, push more setup code into the core auth handler.
+. when moving listeners, if most recent refbuf is not a sync point then use
+  burst point. Fallback theora streams can be affected by this.
+. drop master-redirect-port, use <port>.
+. set <master-redirect> (in slave) non-zero to send IP/port details in
+  streamlist request, so that new listener redirection from master is possible.
+. set <max-redirect-slaves> (in master) to specify the number of slave servers
+  that can request listener redirection, default 0.
+. prevent avg/total byte stats for fallback to file sources.
+. allow for server id to be defined in xml.
+. add connected stat to source, duration in seconds.
+. increase average stats for bitrate calculation to 30 seconds
+. increase sleep duration in connection thread to 100ms
+. make source clients report read bytes in access.log
+. bypass clients limit check for ssl connections, let admin do stuff
+. various type cleanups, gcc4 show various signed/unsigned issues.
+. sync up with trunk, win32, os.h/compat.h, minor type definitions
+
 2.3-kh2
 . merges from post 2.3 release/feedback
   - stats speedup, from order O(n^2) to O(1)

Modified: icecast/branches/kh/icecast/admin/stats.xsl
===================================================================
--- icecast/branches/kh/icecast/admin/stats.xsl	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/admin/stats.xsl	2006-02-17 00:42:03 UTC (rev 10828)
@@ -74,7 +74,7 @@
 <a href="/auth.xsl"><img border="0" src="/images/key.png"/></a> Authentication Required
 </xsl:when>
 <xsl:otherwise>
-<a href="{@mount}.m3u"><img border="0" src="/tunein.png"/></a>
+<a href="{@mount}.m3u"><img border="0" src="/images/tunein.png"/></a>
 </xsl:otherwise>
 </xsl:choose>
 Mount Point : (<xsl:value-of select="@mount" />)

Modified: icecast/branches/kh/icecast/conf/icecast.xml.in
===================================================================
--- icecast/branches/kh/icecast/conf/icecast.xml.in	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/conf/icecast.xml.in	2006-02-17 00:42:03 UTC (rev 10828)
@@ -2,7 +2,6 @@
     <limits>
         <clients>100</clients>
         <sources>2</sources>
-        <threadpool>5</threadpool>
         <queue-size>524288</queue-size>
         <client-timeout>30</client-timeout>
         <header-timeout>15</header-timeout>
@@ -30,10 +29,6 @@
         <yp-url-timeout>15</yp-url-timeout>
         <yp-url>http://dir.xiph.org/cgi-bin/yp-cgi</yp-url>
     </directory>
-    <directory>
-        <yp-url-timeout>15</yp-url-timeout>
-        <yp-url>http://www.oddsock.org/cgi-bin/yp-cgi</yp-url>
-    </directory>
      -->
 
     <!-- This is the hostname other people will use to connect to your server.
@@ -69,9 +64,9 @@
     <!--<relays-on-demand>1</relays-on-demand>-->
 
 
-    <!-- Report <hostname> and this port to master server for redirecting
-         clients to this slave -->
-    <!--<master-redirect-port>8000</master-redirect-port>-->
+    <!-- Request the master server to redirect new listeners to this slave
+         the details passed are based on <hostname> and <port> -->
+    <!--<master-redirect>1</master-redirect>-->
 
     <!-- Relays. State connection information, and by default 
          request inline metadata for mp3 streams if available.

Modified: icecast/branches/kh/icecast/configure.in
===================================================================
--- icecast/branches/kh/icecast/configure.in	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/configure.in	2006-02-17 00:42:03 UTC (rev 10828)
@@ -1,4 +1,4 @@
-AC_INIT([Icecast], [2.3-kh2], [karl at xiph.org])
+AC_INIT([Icecast], [2.3-kh3], [karl at xiph.org])
 
 AC_PREREQ(2.54)
 AC_CONFIG_SRCDIR(src/main.c)

Modified: icecast/branches/kh/icecast/doc/icecast2_listenerauth.html
===================================================================
--- icecast/branches/kh/icecast/doc/icecast2_listenerauth.html	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/doc/icecast2_listenerauth.html	2006-02-17 00:42:03 UTC (rev 10828)
@@ -85,6 +85,7 @@
     &lt;mount&gt;
         &lt;mount-name&gt;/example.ogg&lt;/mount-name&gt;
         &lt;authentication type="url"&gt;
+            &lt;option name="stream_auth" value="http://myauthserver.com/stream_auth.php"/&gt;
             &lt;option name="mount_add" value="http://myauthserver.com/stream_start.php"/&gt;
             &lt;option name="mount_remove" value="http://myauthserver.com/stream_end.php"/&gt;
             &lt;option name="listener_add" value="http://myauthserver.com/listener_joined.php"/&gt;
@@ -98,6 +99,13 @@
 </pre>
 <p>The options are described below in more detail, each of which is optional, but in each
 case, within the POST data, the value for each setting is encoded.</p>
+<h3>stream_auth</h3>
+<p>This URL is for determining whether a source or admin request is allowed to proceed. This
+is only used for source client connections and admin requests which apply to sources.</p>
+<p>POST details are </p>
+<pre>
+    action=stream_auth&amp;mount=&amp;ip=&amp;server=&amp;port=&amp;user=&amp;pass=%s
+</pre>
 <h3>mount_add</h3>
 <p>This URL is for informing the auth server of a stream starting. No listener information
 is passed for this, but can be used to initialise any details the auth server may have.

Modified: icecast/branches/kh/icecast/doc/icecast2_relay.html
===================================================================
--- icecast/branches/kh/icecast/doc/icecast2_relay.html	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/doc/icecast2_relay.html	2006-02-17 00:42:03 UTC (rev 10828)
@@ -22,14 +22,37 @@
 <br />
 <br />
 <h2>Setting Up A Master-Slave Relay</h2>
-<p>In order to setup a relay of this type both servers (the one you wish to relay and the one doing the relaying) need to be icecast2 servers. The following configuration snippet is used as an example:</p>
+<p>In order to setup a relay of this type both servers (the one you wish to relay and the one
+doing the relaying) need to be icecast2 servers. The following configuration snippet is used
+as an example:</p>
 <pre>
     &lt;master-server&gt;192.168.1.11&lt;/master-server&gt;
     &lt;master-server-port&gt;8001&lt;/master-server-port&gt;
     &lt;master-update-interval&gt;120&lt;/master-update-interval&gt;
+    &lt;master-username&gt;relay&lt;/master-username&gt;
     &lt;master-password&gt;hackme&lt;/master-password&gt;
 </pre>
-In this example, this configuration is setup in the server which will be doing the relaying (slave server).  The master server in this case need not be configured (and actually is unaware of the relaying being performed) as a relay.  When the slave server is started, it will connect to the master server located at 192.168.1.11:8001 and will begin to relay all mountpoints connected to the master server.  Additionally, every master-update-interval (120 seconds in this case) the slave server will poll the master server to see if any new mountpoints have connected, and if so, the slave server will relay those as well.  Note that the names of the mountpoints on the slave server will be identical to those on the master server.
+<p>In this example, this configuration is setup in the server which will be doing the relaying
+(slave server).  The master server in this case need not be configured (and actually is unaware
+of the relaying being performed) as a relay.  When the slave server is started, it will connect
+to the master server located at 192.168.1.11:8001 and will begin to relay all non-hidden
+mountpoints connected to the master server.  Additionally, every master-update-interval (120
+seconds in this case) the slave server will poll the master server to see if any new mountpoints
+have connected, and if so, the slave server will relay those as well.  Note that the names of
+the mountpoints on the slave server will be identical to those on the master server.</p>
+<p>To extend on the idea of load sharing, it is possible for a slave icecast2 to communicate
+certain information to allow for new listeners to be redirected from the master server to the
+slave. In such cases, the master will send to the listener a HTTP 302 response code with a URL
+of the slave server which has been randomly selected.</p>
+</p>To enable this certain settings have to be enabled. In the master</p>
+<pre>
+    &lt;max-redirect-slaves&gt;5&lt;/max-redirect-slaves&gt;
+</pre>
+<p>This limits the redirection mechanism to 5 slaves, the default is 0, preventing any attempts
+to redirect new listeners. In the slave </p>
+<pre>
+    &lt;master-redirect&gt;1&lt;/master-redirect&gt;
+</pre>
 <br />
 <br />
 <br />

Modified: icecast/branches/kh/icecast/src/admin.c
===================================================================
--- icecast/branches/kh/icecast/src/admin.c	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/src/admin.c	2006-02-17 00:42:03 UTC (rev 10828)
@@ -1160,6 +1160,9 @@
         ice_config_t *config = config_get_config ();
         mount_proxy *mountinfo = config->mounts;
 
+        /* do any redirector updates */
+        redirector_update (client);
+
         buf = client->refbuf->data;
         ret = snprintf (buf, remaining,
                 "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");

Modified: icecast/branches/kh/icecast/src/auth.c
===================================================================
--- icecast/branches/kh/icecast/src/auth.c	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/src/auth.c	2006-02-17 00:42:03 UTC (rev 10828)
@@ -410,7 +410,7 @@
             DEBUG0 ("client authenticated, passed to source");
         else
         {
-            if (slave_redirect (mount, client))
+            if (redirect_client (mount, client))
                 ret = 0;
         }
     }
@@ -472,7 +472,7 @@
 
     if (connection_check_relay_pass(client->parser))
     {
-        client_as_slave (client);
+        client->is_slave = 1;
         INFO0 ("client connected as slave");
     }
     config = config_get_config();

Modified: icecast/branches/kh/icecast/src/auth_url.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_url.c	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/src/auth_url.c	2006-02-17 00:42:03 UTC (rev 10828)
@@ -408,7 +408,7 @@
 {
     client_t *client = auth_user->client;
     auth_url *url = client->auth->state;
-    char *mount, *host, *user, *pass, *ipaddr, *metadata="";
+    char *mount, *host, *user, *pass, *ipaddr, *admin="";
     char post [4096];
 
     if (strchr (url->stream_auth, '@') == NULL)
@@ -426,7 +426,7 @@
     if (strncmp (auth_user->mount, "/admin/", 7) == 0)
     {
         mount = util_url_escape (httpp_get_query_param (client->parser, "mount"));
-        metadata = "&metadata=1";
+        admin = "&admin=1";
     }
     else
         mount = util_url_escape (auth_user->mount);
@@ -436,8 +436,8 @@
     ipaddr = util_url_escape (client->con->ip);
 
     snprintf (post, sizeof (post),
-            "action=stream_auth&mount=%sip=%s&server=%s&port=%d&user=%s&pass=%s%s",
-            mount, ipaddr, host, auth_user->port, user, pass, metadata);
+            "action=stream_auth&mount=%s&ip=%s&server=%s&port=%d&user=%s&pass=%s%s",
+            mount, ipaddr, host, auth_user->port, user, pass, admin);
     free (ipaddr);
     free (user);
     free (pass);

Modified: icecast/branches/kh/icecast/src/cfgfile.c
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.c	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/src/cfgfile.c	2006-02-17 00:42:03 UTC (rev 10828)
@@ -367,7 +367,6 @@
     configuration->master_username = (char*)xmlCharStrdup (CONFIG_DEFAULT_MASTER_USERNAME);
     configuration->master_password = NULL;
     configuration->master_relay_auth = 0;
-    configuration->master_redirect_port = 0;
     configuration->base_dir = CONFIG_DEFAULT_BASE_DIR;
     configuration->log_dir = CONFIG_DEFAULT_LOG_DIR;
     configuration->webroot_dir = CONFIG_DEFAULT_WEBROOT_DIR;
@@ -458,10 +457,6 @@
             tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
             configuration->master_server_port = atoi(tmp);
             xmlFree (tmp);
-        } else if (xmlStrcmp(node->name, XMLSTR ("master-redirect-port")) == 0) {
-            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
-            configuration->master_redirect_port = atoi(tmp);
-            xmlFree (tmp);
         } else if (xmlStrcmp(node->name, XMLSTR ("master-update-interval")) == 0) {
             tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
             configuration->master_update_interval = atoi(tmp);
@@ -474,6 +469,14 @@
             tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
             configuration->master_ssl_port = atoi(tmp);
             xmlFree (tmp);
+        } else if (xmlStrcmp(node->name, XMLSTR ("master-redirect")) == 0) {
+            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+            configuration->master_redirect = atoi(tmp);
+            xmlFree (tmp);
+        } else if (xmlStrcmp(node->name, XMLSTR ("max-redirect-slaves")) == 0) {
+            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+            configuration->max_redirects = atoi(tmp);
+            xmlFree (tmp);
         } else if (xmlStrcmp(node->name, XMLSTR ("shoutcast-mount")) == 0) {
             if (configuration->shoutcast_mount &&
                     configuration->shoutcast_mount != CONFIG_DEFAULT_SHOUTCAST_MOUNT)
@@ -495,6 +498,8 @@
             _parse_security(doc, node->xmlChildrenNode, configuration);
         }
     } while ((node = node->next));
+    if (configuration->max_redirects == 0 && configuration->master_redirect)
+        configuration->max_redirects = 1;
 }
 
 static void _parse_limits(xmlDocPtr doc, xmlNodePtr node, 

Modified: icecast/branches/kh/icecast/src/cfgfile.h
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.h	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/src/cfgfile.h	2006-02-17 00:42:03 UTC (rev 10828)
@@ -144,6 +144,8 @@
     char *master_password;
     int master_relay_auth;
     int master_ssl_port;
+    int master_redirect;
+    int max_redirects;
 
     relay_server *relay;
 
@@ -158,7 +160,6 @@
     char *adminroot_dir;
     aliases *aliases;
     unsigned slaves_count;
-    int master_redirect_port;
 
     char *access_log;
     char *error_log;

Modified: icecast/branches/kh/icecast/src/client.c
===================================================================
--- icecast/branches/kh/icecast/src/client.c	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/src/client.c	2006-02-17 00:42:03 UTC (rev 10828)
@@ -119,8 +119,6 @@
             ;
     }
 #endif
-    if (client->is_slave)
-        slave_host_remove (client);
 
     if (client->con)
         connection_close(client->con);
@@ -171,12 +169,12 @@
 }
 
 
-void client_send_302(client_t *client, char *location) {
+void client_send_302(client_t *client, const char *location) {
     snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
             "HTTP/1.0 302 Temporarily Moved\r\n"
             "Content-Type: text/html\r\n"
             "Location: %s\r\n\r\n"
-            "<a href=\"%s\">%s</a>", location, location, location);
+            "Moved <a href=\"%s\">here</a>\r\n", location, location);
     client->respcode = 302;
     client->refbuf->len = strlen (client->refbuf->data);
     fserve_add_client (client, NULL);
@@ -296,16 +294,3 @@
         refbuf_release (to_release);
 }
 
-void client_as_slave (client_t *client)
-{
-    char *slave_redirect = httpp_getvar (client->parser, "ice-redirect");
-    INFO1 ("client connected as slave from %s", client->con->ip);
-    client->is_slave = 1;
-    if (slave_redirect)
-    {
-        /* this will be something like ip:port */
-        DEBUG1 ("header for auth slave is \"%s\"", slave_redirect);
-        slave_host_add (client, slave_redirect);
-    }
-}
-

Modified: icecast/branches/kh/icecast/src/client.h
===================================================================
--- icecast/branches/kh/icecast/src/client.h	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/src/client.h	2006-02-17 00:42:03 UTC (rev 10828)
@@ -92,10 +92,9 @@
 void client_send_401(client_t *client);
 void client_send_403(client_t *client, const char *reason);
 void client_send_400(client_t *client, char *message);
-void client_send_302(client_t *client, char *location);
+void client_send_302(client_t *client, const char *location);
 int client_send_bytes (client_t *client, const void *buf, unsigned len);
 int client_read_bytes (client_t *client, void *buf, unsigned len);
 void client_set_queue (client_t *client, refbuf_t *refbuf);
-void client_as_slave (client_t *client);
 
 #endif  /* __CLIENT_H__ */

Modified: icecast/branches/kh/icecast/src/connection.c
===================================================================
--- icecast/branches/kh/icecast/src/connection.c	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/src/connection.c	2006-02-17 00:42:03 UTC (rev 10828)
@@ -1227,7 +1227,7 @@
             }
             continue;
         }
-        thread_sleep (50000);
+        thread_sleep (100000);
     }
     DEBUG0 ("Connection thread done");
 

Modified: icecast/branches/kh/icecast/src/format.c
===================================================================
--- icecast/branches/kh/icecast/src/format.c	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/src/format.c	2006-02-17 00:42:03 UTC (rev 10828)
@@ -90,8 +90,8 @@
     default:
         break;
     }
-    source->format->in_bitrate = rate_setup (10);
-    source->format->out_bitrate = rate_setup (10);
+    source->format->in_bitrate = rate_setup (30);
+    source->format->out_bitrate = rate_setup (30);
 
     return ret;
 }
@@ -104,8 +104,10 @@
 {
     refbuf_t *refbuf = source->burst_point;
 
-    /* we only want to attempt a burst at connection time, not midstream */
-    if (client->intro_offset == -1)
+    /* we only want to attempt a burst at connection time, not midstream
+     * however streams like theora may not have the most recent page marked as
+     * a starting point, so look for one from the burst point */
+    if (client->intro_offset == -1 && source->stream_data_tail->sync_point)
         refbuf = source->stream_data_tail;
     else
     {

Modified: icecast/branches/kh/icecast/src/global.h
===================================================================
--- icecast/branches/kh/icecast/src/global.h	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/src/global.h	2006-02-17 00:42:03 UTC (rev 10828)
@@ -44,9 +44,9 @@
     /* relays retrieved from master */
     struct _relay_server *master_relays;
 
-    /* slave relay list */
-    unsigned int slave_count;
-    struct _slave_host *slaves;
+    /* redirection to slaves */
+    unsigned int redirect_count;
+    struct _redirect_host *redirectors;
 
     cond_t shutdown_cond;
 } ice_global_t;

Modified: icecast/branches/kh/icecast/src/slave.c
===================================================================
--- icecast/branches/kh/icecast/src/slave.c	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/src/slave.c	2006-02-17 00:42:03 UTC (rev 10828)
@@ -62,8 +62,9 @@
 #define CATMODULE "slave"
 
 static void *_slave_thread(void *arg);
-static void _add_slave_host (const char *server, int port);
-static slave_host *find_slave_host (const char *server, int port);
+static void redirector_add (const char *server, int port, int interval);
+static redirect_host *find_slave_host (const char *server, int port);
+static void redirector_clearall (void);
 
 static thread_type *_slave_thread_id;
 static int slave_running = 0;
@@ -140,6 +141,9 @@
     thread_rwlock_create (&slaves_lock);
     slave_running = 1;
     max_interval = 0;
+#ifndef HAVE_CURL
+    WARN0 ("streamlist request disabled, rebuild with libcurl if required");
+#endif
     _slave_thread_id = thread_create("Slave Thread", _slave_thread, NULL, THREAD_ATTACHED);
 }
 
@@ -155,45 +159,60 @@
 }
 
 
-int slave_redirect (const char *mountpoint, client_t *client)
+int redirect_client (const char *mountpoint, client_t *client)
 {
-    slave_host *slave = NULL;
+    int ret = 0, which;
+    redirect_host *checking, **trail;
 
-    DEBUG1 ("slave count is %d", global.slave_count);
     thread_rwlock_rlock (&slaves_lock);
     /* select slave entry */
-    if (global.slave_count)
+    if (global.redirect_count == 0)
     {
-        int which=(int) (((float)global.slave_count)*rand()/(RAND_MAX+1.0));
-        slave = global.slaves;
-        while (slave && which)
+        thread_rwlock_unlock (&slaves_lock);
+        return 0;
+    }
+    which=(int) (((float)global.redirect_count)*rand()/(RAND_MAX+1.0)) + 1;
+    checking = global.redirectors;
+    trail = &global.redirectors;
+
+    DEBUG2 ("random selection %d (out of %d)", which, global.redirect_count);
+    while (checking)
+    {
+        DEBUG2 ("...%s:%d", checking->server, checking->port);
+        if (checking->next_update && checking->next_update+10 < global.time)
         {
-            slave = slave->next;
-            which--;
+            /* no streamist request, expire slave for now */
+            *trail = checking->next;
+            global.redirect_count--;
+            /* free slave details */
+            INFO2 ("dropping redirector for %s:%d", checking->server, checking->port);
+            free (checking->server);
+            free (checking);
+            checking = *trail;
+            if (which > 0)
+                which--; /* we are 1 less now */
+            continue;
         }
-        DEBUG2 ("selected %s:%d", slave->server,slave->port);
-    }
-    if (slave)
-    {
-        char *location = NULL;
-        /* add 13 for "http://" the port ':' and nul */
-        int len = strlen(mountpoint) + strlen (slave->server) + 13;
+        if (--which == 0)
+        {
+            char *location;
+            /* add enough for "http://" the port ':' and nul */
+            int len = strlen (mountpoint) + strlen (checking->server) + 13;
 
-        location = malloc (len);
-        if (location)
-        {
             INFO2 ("redirecting client to slave server "
-                    "at %s:%d", slave->server, slave->port);
-            snprintf (location, len, "http://%s:%d%s", slave->server,
-                    slave->port, mountpoint);
-            thread_rwlock_unlock (&slaves_lock);
+                    "at %s:%d", checking->server, checking->port);
+            location = malloc (len);
+            snprintf (location, len, "http://%s:%d%s", checking->server,
+                    checking->port, mountpoint);
             client_send_302 (client, location);
             free (location);
-            return 1;
+            ret = 1;
         }
+        trail = &checking->next;
+        checking = checking->next;
     }
     thread_rwlock_unlock (&slaves_lock);
-    return 0;
+    return ret;
 }
 
 
@@ -214,7 +233,7 @@
     do
     {
         char *auth_header;
-        char *redirect_header = NULL, *server_id;
+        char *server_id;
         ice_config_t *config;
 
         streamsock = sock_connect_wto (relay->server, relay->port, 10);
@@ -242,22 +261,10 @@
             snprintf (auth_header, len,
                     "Authorization: Basic %s\r\n", esc_authorisation);
             free(esc_authorisation);
-
-            /* header to use for participating in load sharing */
-            if (config->master_redirect_port)
-            {
-                len = strlen ("ice-redirect:") + strlen (config->hostname) + 10;
-                redirect_header = malloc (len);
-                snprintf (redirect_header, len, "ice-redirect: %s:%d\r\n",
-                        config->hostname, config->master_redirect_port);
-            }
-            else
-                redirect_header = strdup ("");
         }
         else
         {
             auth_header = strdup ("");
-            redirect_header = strdup ("");
         }
         config_release_config ();
 
@@ -270,16 +277,13 @@
                 "User-Agent: %s\r\n"
                 "%s"
                 "%s"
-                "%s"
                 "\r\n",
                 relay->mount,
                 server_id,
                 relay->mp3metadata?"Icy-MetaData: 1\r\n":"",
-                redirect_header,
                 auth_header);
         free (server_id);
         free (auth_header);
-        free (redirect_header);
         memset (header, 0, sizeof(header));
         if (util_read_header (con->sock, header, 4096, READ_ENTIRE_HEADER) == 0)
         {
@@ -380,7 +384,10 @@
         /* new relay, reserve the name */
         relay->source = source_reserve (relay->localmount);
         if (relay->source)
+        {
             DEBUG1("Adding relay source at mountpoint \"%s\"", relay->localmount);
+            relay->cleanup = 1;
+        }
         else
             WARN1 ("new relay but source \"%s\" already exists", relay->localmount);
     }
@@ -395,16 +402,8 @@
             stats_event (relay->localmount, NULL, NULL);
             break;
         }
-        if (relay->on_demand)
+        if (relay->on_demand && source->on_demand_req == 0)
         {
-            ice_config_t *config = config_get_config ();
-            mount_proxy *mountinfo = config_find_mount (config, relay->localmount);
-
-            if (mountinfo == NULL)
-                source_update_settings (config, relay->source, mountinfo);
-            config_release_config ();
-            slave_rebuild_mounts();
-            stats_event (relay->localmount, "listeners", "0");
             relay->source->on_demand = relay->on_demand;
 
             if (source->fallback_mount && source->fallback_override)
@@ -431,11 +430,14 @@
 
     } while (0);
     /* the relay thread may of shut down itself */
-    if (relay->cleanup && relay->thread)
+    if (relay->cleanup)
     {
-        DEBUG1 ("waiting for relay thread for \"%s\"", relay->localmount);
-        thread_join (relay->thread);
-        relay->thread = NULL;
+        if (relay->thread)
+        {
+            DEBUG1 ("waiting for relay thread for \"%s\"", relay->localmount);
+            thread_join (relay->thread);
+            relay->thread = NULL;
+        }
         relay->cleanup = 0;
         relay->running = 0;
 
@@ -541,7 +543,8 @@
 }
 
 
-static void relay_check_streams (relay_server *to_start, relay_server *to_free, int skip_timer)
+static void relay_check_streams (relay_server *to_start,
+        relay_server *to_free, int skip_timer)
 {
     relay_server *relay;
 
@@ -588,6 +591,7 @@
     char *username;
     char *password;
     char *server_id;
+    char *args;
     relay_server *new_relays;
 };
 
@@ -701,7 +705,7 @@
     const char *protocol = "http";
     int port = master->port;
     char error [CURL_ERROR_SIZE];
-    char url [300], auth [100];
+    char url [1024], auth [100];
 
     if (master->ssl_port)
     {
@@ -709,8 +713,8 @@
         port = master->ssl_port;
     }
     snprintf (auth, sizeof (auth), "%s:%s", master->username, master->password);
-    snprintf (url, sizeof (url), "%s://%s:%d/admin/streamlist.txt",
-            protocol, master->server, port);
+    snprintf (url, sizeof (url), "%s://%s:%d/admin/streamlist.txt%s",
+            protocol, master->server, port, master->args);
     handle = curl_easy_init ();
     curl_easy_setopt (handle, CURLOPT_USERAGENT, master->server_id);
     curl_easy_setopt (handle, CURLOPT_URL, url);
@@ -746,6 +750,7 @@
     free (master->password);
     free (master->buffer);
     free (master->server_id);
+    free (master->args);
     free (master);
     return NULL;
 }
@@ -769,24 +774,39 @@
     details->send_auth = config->master_relay_auth;
     details->on_demand = config->on_demand;
     details->server_id = strdup (config->server_id);
+    if (config->master_redirect)
+    {
+        details->args = malloc (4096);
+        snprintf (details->args, 4096, "?rserver=%s&rport=%d&interval=%d",
+                config->hostname, config->port, config->master_update_interval);
+    }
+    else
+        details->args = strdup ("");
 
     thread_create ("streamlist", streamlist_thread, details, THREAD_DETACHED);
-#else
-    WARN0 ("streamlist request disabled, rebuild with libcurl if required");
 #endif
 }
 
 
 static void update_master_as_slave (ice_config_t *config)
 {
-    if (config->master_server == NULL || config->master_redirect_port == 0)
+    redirect_host *redirect;
+
+    if (config->master_server == NULL || config->master_redirect == 0 || config->max_redirects == 0)
+    {
+        redirector_clearall();
         return;
+    }
 
     thread_rwlock_wlock (&slaves_lock);
-    DEBUG1 ("redirect port is %d", config->master_redirect_port);
-    if (find_slave_host (config->master_server,
-                config->master_server_port) == NULL)
-        _add_slave_host (config->master_server, config->master_server_port);
+    redirect = find_slave_host (config->master_server, config->master_server_port);
+    if (redirect == NULL)
+    {
+        INFO2 ("adding master %s:%d", config->master_server, config->master_server_port);
+        redirector_add (config->master_server, config->master_server_port, 0);
+    }
+    else
+        redirect->next_update += max_interval;
     thread_rwlock_unlock (&slaves_lock);
 }
 
@@ -852,6 +872,7 @@
     INFO0 ("shutting down current relays");
     relay_check_streams (NULL, global.relays, 0);
     relay_check_streams (NULL, global.master_relays, 0);
+    redirector_clearall();
 
     INFO0 ("Slave thread shutdown complete");
 
@@ -871,108 +892,100 @@
 }
 
 
-/* remove this slave clients entry in the slave host list */
-void slave_host_remove (client_t *client)
+/* drop all redirection details.
+ */
+static void redirector_clearall (void)
 {
-    const char *var = httpp_getvar (client->parser, "ice-redirect");
-
-    if (var)
+    thread_rwlock_wlock (&slaves_lock);
+    while (global.redirectors)
     {
-        slave_host *slave, **trail;
-        char *server = strdup (var), *separator;
-        int port;
-
-        separator = strchr (server, ':');
-        if (separator == NULL)
-        {
-            free (server);
-            return;
-        }
-        *separator = '\0';
-        port = atoi (separator+1);
-        thread_rwlock_wlock (&slaves_lock);
-        slave = global.slaves;
-        trail = &global.slaves;
-        while (slave)
-        {
-            if (strcmp (slave->server, server) == 0 && slave->port == port)
-            {
-                slave->count--;
-                if (slave->count == 0)
-                {
-                    INFO2 ("slave at %s:%d removed", slave->server, slave->port);
-                    *trail = slave->next;
-                    free (slave->server);
-                    global.slave_count--;
-                }
-                break;
-            }
-            trail = &slave->next;
-            slave = slave->next;
-        }
-        thread_rwlock_unlock (&slaves_lock);
+        redirect_host *current = global.redirectors;
+        global.redirectors = current->next;
+        free (current->server);
+        free (current);
     }
+    global.redirect_count = 0;
+    thread_rwlock_unlock (&slaves_lock);
 }
 
-
-/* with the provided header (eg "localhost:8000") add a new slave host
- * entry to so that clients can redirect to other sites when full
+/* Add new redirectors or update any existing ones
  */
-void slave_host_add (client_t *client, const char *header)
+void redirector_update (client_t *client)
 {
-    slave_host *slave;
-    char *server, *separator;
-    int port;
+    redirect_host *redirect;
+    const char *rserver = httpp_get_query_param (client->parser, "rserver");
+    char *value;
+    int rport, interval;
 
-    if (client == NULL || header == NULL)
-        return;
+    if (rserver==NULL) return;
+    value = httpp_get_query_param (client->parser, "rport");
+    if (value == NULL) return;
+    rport = atoi (value);
+    if (rport <= 0) return;
+    value = httpp_get_query_param (client->parser, "interval");
+    if (value == NULL) return;
+    interval = atoi (value);
+    if (interval < 5) return;
 
-    server = strdup (header);
-    separator = strchr (server, ':');
-    if (separator == NULL)
+
+    thread_rwlock_wlock (&slaves_lock);
+    redirect = find_slave_host (rserver, rport);
+    if (redirect == NULL)
     {
-        free (server);
-        return;
+        redirector_add (rserver, rport, interval);
     }
-    *separator = '\0';
-    port = atoi (separator+1);
-    thread_rwlock_wlock (&slaves_lock);
-    slave = find_slave_host (server, port);
-    if (slave)
+    else
     {
-        slave->count++;
-        DEBUG0 ("already exists, increasing count");
+        DEBUG2 ("touch update on %s:%d", redirect->server, redirect->port);
+        redirect->next_update = global.time + interval;
     }
-    else
-        _add_slave_host (server, port);
     thread_rwlock_unlock (&slaves_lock);
-    free (server);
 }
 
-static slave_host *find_slave_host (const char *server, int port)
+
+
+/* search list of redirectors for a matching entry, lock must be held before
+ * invoking this function
+ */
+static redirect_host *find_slave_host (const char *server, int port)
 {
-    slave_host *slave = global.slaves;
-    while (slave)
+    redirect_host *redirect = global.redirectors;
+    while (redirect)
     {
-        if (strcmp (slave->server, server) == 0 && slave->port == port)
+        if (strcmp (redirect->server, server) == 0 && redirect->port == port)
             break;
-        slave = slave->next;
+        redirect = redirect->next;
     }
-    return slave;
+    return redirect;
 }
 
-static void _add_slave_host (const char *server, int port)
+
+static void redirector_add (const char *server, int port, int interval)
 {
-    slave_host *slave = calloc (1, sizeof (slave_host));
-    if (slave == NULL)
+    ice_config_t *config = config_get_config();
+    int allowed = config->max_redirects;
+    redirect_host *redirect;
+
+    config_release_config();
+
+    if (global.redirect_count >= allowed)
+    {
+        INFO1 ("redirect to slave limit reached (%d)", global.redirect_count);
         return;
-    slave->server = strdup (server);
-    slave->port = port;
-    slave->count = 1;
-    slave->next = global.slaves;
-    global.slaves = slave;
-    global.slave_count++;
-    INFO3 ("slave (%d) at %s:%d added", global.slave_count,
-            slave->server, slave->port);
+    }
+    redirect = calloc (1, sizeof (redirect_host));
+    if (redirect == NULL)
+        abort();
+    redirect->server = strdup (server);
+    redirect->port = port;
+    if (interval == 0)
+        redirect->next_update = (time_t)0;
+    else
+        redirect->next_update = global.time + interval;
+    redirect->next = global.redirectors;
+    global.redirectors = redirect;
+    global.redirect_count++;
+    INFO3 ("slave (%d) at %s:%d added", global.redirect_count,
+            redirect->server, redirect->port);
 }
 

Modified: icecast/branches/kh/icecast/src/slave.h
===================================================================
--- icecast/branches/kh/icecast/src/slave.h	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/src/slave.h	2006-02-17 00:42:03 UTC (rev 10828)
@@ -35,22 +35,21 @@
     struct _relay_server *next;
 } relay_server;
 
-typedef struct _slave_host
+typedef struct _redirect_host
 {
     char *server;
     int port;
-    unsigned int count;
-    struct _slave_host *next;
-} slave_host;
+    time_t next_update;
+    struct _redirect_host *next;
+} redirect_host;
 
 void slave_initialize(void);
 void slave_shutdown(void);
 void slave_recheck_mounts (void);
 void slave_rebuild_mounts (void);
 relay_server *slave_find_relay (relay_server *relays, const char *mount);
-int slave_redirect (const char *mountpoint, struct _client_tag *client);
-void slave_host_add (struct _client_tag *client, const char *header);
-void slave_host_remove (struct _client_tag *client);
+int redirect_client (const char *mountpoint, struct _client_tag *client);
+void redirector_update (struct _client_tag *client);
 relay_server *relay_free (relay_server *relay);
 
 #endif  /* __SLAVE_H__ */

Modified: icecast/branches/kh/icecast/src/source.c
===================================================================
--- icecast/branches/kh/icecast/src/source.c	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/src/source.c	2006-02-17 00:42:03 UTC (rev 10828)
@@ -436,16 +436,18 @@
         /* take the lock */
         thread_mutex_lock (&source->lock);
 
-        if (current >= source->client_stats_update)
+        if (source->client && current >= source->client_stats_update)
         {
             stats_event_args (source->mount, "outgoing_bitrate", "%ld", 
-                    8 * rate_avg (source->format->out_bitrate));
+                    (8 * rate_avg (source->format->out_bitrate))/1000);
             stats_event_args (source->mount, "incoming_bitrate", "%ld", 
-                    8 * rate_avg (source->format->in_bitrate));
+                    (8 * rate_avg (source->format->in_bitrate))/1000);
             stats_event_args (source->mount, "total_bytes_read",
                     FORMAT_UINT64, source->format->read_bytes);
             stats_event_args (source->mount, "total_bytes_sent",
                     FORMAT_UINT64, source->format->sent_bytes);
+            stats_event_args (source->mount, "connected", FORMAT_UINT64,
+                    (uint64_t)(current - source->client->con->con_time));
             source->client_stats_update = current + 5;
         }
         if (fds < 0)

Modified: icecast/branches/kh/icecast/src/yp.c
===================================================================
--- icecast/branches/kh/icecast/src/yp.c	2006-02-16 14:36:17 UTC (rev 10827)
+++ icecast/branches/kh/icecast/src/yp.c	2006-02-17 00:42:03 UTC (rev 10828)
@@ -91,6 +91,7 @@
 static time_t now;
 static thread_type *yp_thread;
 static volatile unsigned client_limit = 0;
+static volatile char *server_version = NULL;
 
 static void *yp_update_thread(void *arg);
 static void add_yp_info (ypdata_t *yp, void *info, int type);
@@ -217,6 +218,8 @@
         server = server->next;
     }
     client_limit = config->client_limit;
+    free (server_version);
+    server_version = strdup (config->server_id);
     /* for each yp url in config, check to see if one exists 
        if not, then add it. */
     for (i=0 ; i < config->num_yp_directories; i++)
@@ -242,7 +245,7 @@
             }
             if (server->touch_interval < 30)
                 server->touch_interval = 30;
-            curl_easy_setopt (server->curl, CURLOPT_USERAGENT, ICECAST_VERSION_STRING);
+            curl_easy_setopt (server->curl, CURLOPT_USERAGENT, server_version);
             curl_easy_setopt (server->curl, CURLOPT_URL, server->url);
             curl_easy_setopt (server->curl, CURLOPT_HEADERFUNCTION, handle_returned_header);
             curl_easy_setopt (server->curl, CURLOPT_WRITEFUNCTION, handle_returned_data);
@@ -354,6 +357,8 @@
     free (value);
 
     value = stats_get_value (yp->mount, "bitrate");
+    if (value == NULL)
+        value = stats_get_value (yp->mount, "incoming_bitrate");
     add_yp_info (yp, value, YP_BITRATE);
     free (value);
 
@@ -845,7 +850,7 @@
                 yp->server = server;
                 yp->touch_interval = server->touch_interval;
                 yp->next = server->pending_mounts;
-                yp->next_update = time(NULL) + 5;
+                yp->next_update = global.time + 60;
                 server->pending_mounts = yp;
                 yp_update = 1;
             }
@@ -925,6 +930,8 @@
     if (yp_thread)
         thread_join (yp_thread);
     curl_global_cleanup();
+    free (server_version);
+    server_version = NULL;
     INFO0 ("YP thread down");
 }
 



More information about the commits mailing list