[xiph-commits] r7659 - in icecast/branches/kh/icecast: conf doc src

karl at motherfish-iii.xiph.org karl at motherfish-iii.xiph.org
Sun Aug 29 08:17:15 PDT 2004


Author: karl
Date: 2004-08-29 08:17:14 -0700 (Sun, 29 Aug 2004)
New Revision: 7659

Modified:
   icecast/branches/kh/icecast/conf/icecast.xml.in
   icecast/branches/kh/icecast/doc/icecast2_config_file.html
   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/global.h
   icecast/branches/kh/icecast/src/slave.c
   icecast/branches/kh/icecast/src/slave.h
   icecast/branches/kh/icecast/src/source.c
Log:
build the slave host list by using the connecting relay-authenticated master relays
instead of using the xml.  Update docs and example xml


Modified: icecast/branches/kh/icecast/conf/icecast.xml.in
===================================================================
--- icecast/branches/kh/icecast/conf/icecast.xml.in	2004-08-28 20:42:10 UTC (rev 7658)
+++ icecast/branches/kh/icecast/conf/icecast.xml.in	2004-08-29 15:17:14 UTC (rev 7659)
@@ -58,19 +58,6 @@
     </listen-socket>
     -->
 
-    <!-- when full, redirect listeners to the listed slaves -->
-    <!--
-    <slave-host>
-        <server>somehost.com</server>
-        <port>8000</port>
-    </slave-host> 
-
-    <slave-host>
-        <server>someotherhost.com</server>
-        <port>8000</port>
-    </slave-host> 
-    -->
-
     <!--<relays-on-demand>1</relays-on-demand>-->
     <!--<master-server>127.0.0.1</master-server>-->
     <!--<master-server-port>8001</master-server-port>-->
@@ -78,6 +65,10 @@
     <!--<master-password>hackme</master-password>-->
     <!--<master-relay-auth>1</master-relay-auth>-->
 
+    <!-- Report <hostname> and this port to master server for redirecting
+         clients to this slave -->
+    <!--<master-redirect-port>8000</master-redirect-port>-->
+
     <!-- Relays. State connection information, and by default 
          request inline metadata for mp3 streams if available.
          An on-demand relay will only retrieve the stream if

Modified: icecast/branches/kh/icecast/doc/icecast2_config_file.html
===================================================================
--- icecast/branches/kh/icecast/doc/icecast2_config_file.html	2004-08-28 20:42:10 UTC (rev 7658)
+++ icecast/branches/kh/icecast/doc/icecast2_config_file.html	2004-08-29 15:17:14 UTC (rev 7659)
@@ -215,10 +215,23 @@
 <div class=indentedbox>
 The interval (in seconds) that the Relay Server will poll the Master Server for any new mountpoints to relay.
 </div>
+<h4>master-username</h4>
+<div class=indentedbox>
+This is the username to authenticate with the master. The default is "relay". This is used to
+get hold of the streamlist and can be used to authenticate master relays. The master server
+will compare with the relay-user.
+</div>
 <h4>master-password</h4>
 <div class=indentedbox>
-This is the admin password on the Master server.  It is used to query the server for a list of mountpoints to relay.
+As with master-username, this is the password to authenticate with the master server. The
+relay-password on the master server is used for comparison.
 </div>
+<h4>master-redirect-port</h4>
+<div class=indentedbox>
+When a slave starts a master relay using authentication, then a host and port can also be sent to
+inform the master for the purposes of redirecting clients to the slave. The host is provided by
+the hostname setting and this specifies the port to redirect listeners to.
+</div>
 <h4>relays-on-demand</h4>
 <div class=indentedbox>
 Changes the default on-demand setting, so a stream is only relayed if listeners are connected.

Modified: icecast/branches/kh/icecast/src/cfgfile.c
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.c	2004-08-28 20:42:10 UTC (rev 7658)
+++ icecast/branches/kh/icecast/src/cfgfile.c	2004-08-29 15:17:14 UTC (rev 7659)
@@ -77,7 +77,6 @@
 static void _parse_security(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
 static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node, 
         ice_config_t *c);
-static void _parse_slave_host(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
 static void _parse_relay(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
 static void _parse_mount(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
 static void _parse_listen_socket(xmlDocPtr doc, xmlNodePtr node, 
@@ -119,7 +118,6 @@
     relay_server *relay, *nextrelay;
     mount_proxy *mount, *nextmount;
     aliases *alias, *nextalias;
-    slave_host *slave;
     int i;
     config_options_t *option;
 
@@ -221,14 +219,6 @@
         free(dirnode);
         dirnode = nextdirnode;
     }
-    slave = c->slave_list;
-    while (slave)
-    {
-        slave_host *to_go = slave;
-        slave = slave->next;
-        xmlFree (to_go->server);
-        free (to_go);
-    }
 #ifdef HAVE_YP
     i = 0;
     while (i < c->num_yp_directories)
@@ -348,6 +338,7 @@
     configuration->master_username = NULL;
     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;
@@ -434,6 +425,10 @@
             tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
             configuration->master_server_port = atoi(tmp);
             xmlFree (tmp);
+        } else if (strcmp(node->name, "master-redirect-port") == 0) {
+            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+            configuration->master_redirect_port = atoi(tmp);
+            xmlFree (tmp);
         } else if (strcmp(node->name, "master-update-interval") == 0) {
             tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
             configuration->master_update_interval = atoi(tmp);
@@ -446,8 +441,6 @@
             _parse_limits(doc, node->xmlChildrenNode, configuration);
         } else if (strcmp(node->name, "relay") == 0) {
             _parse_relay(doc, node->xmlChildrenNode, configuration);
-        } else if (strcmp(node->name, "slave-host") == 0) {
-            _parse_slave_host(doc, node->xmlChildrenNode, configuration);
         } else if (strcmp(node->name, "mount") == 0) {
             _parse_mount(doc, node->xmlChildrenNode, configuration);
         } else if (strcmp(node->name, "directory") == 0) {
@@ -650,37 +643,7 @@
     } while ((node = node->next));
 }
 
-static void _parse_slave_host(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c)
-{
-    slave_host *slave = calloc(1, sizeof(slave_host));
-    xmlChar *tmp;
 
-    slave->port = 8000;
-
-    do {
-        if (node == NULL) break;
-        if (xmlIsBlankNode(node)) continue;
-
-        if (strcmp(node->name, "server") == 0) {
-            slave->server = (char *)xmlNodeListGetString(
-                    doc, node->xmlChildrenNode, 1);
-        }
-        else if (strcmp(node->name, "port") == 0) {
-            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
-            slave->port = atoi(tmp);
-            if(tmp) xmlFree(tmp);
-        }
-    } while ((node = node->next));
-    if (slave->server)
-    {
-        slave->next = c->slave_list;
-        c->slave_list = slave;
-        c->slaves_count++;
-        return;
-    }
-    free (slave);
-}
-
 static void _parse_relay(xmlDocPtr doc, xmlNodePtr node,
         ice_config_t *configuration)
 {

Modified: icecast/branches/kh/icecast/src/cfgfile.h
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.h	2004-08-28 20:42:10 UTC (rev 7658)
+++ icecast/branches/kh/icecast/src/cfgfile.h	2004-08-29 15:17:14 UTC (rev 7659)
@@ -135,8 +135,8 @@
     char *webroot_dir;
     char *adminroot_dir;
     aliases *aliases;
-    slave_host *slave_list;
     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	2004-08-28 20:42:10 UTC (rev 7658)
+++ icecast/branches/kh/icecast/src/client.c	2004-08-29 15:17:14 UTC (rev 7659)
@@ -70,6 +70,9 @@
             ;
     }
 #endif
+    if (client->is_slave)
+        slave_host_remove (client);
+
     connection_close(client->con);
     httpp_destroy(client->parser);
 
@@ -198,3 +201,16 @@
         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	2004-08-28 20:42:10 UTC (rev 7658)
+++ icecast/branches/kh/icecast/src/client.h	2004-08-29 15:17:14 UTC (rev 7659)
@@ -82,5 +82,6 @@
 void client_send_302(client_t *client, char *location);
 int client_send_bytes (client_t *client, const 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/global.h
===================================================================
--- icecast/branches/kh/icecast/src/global.h	2004-08-28 20:42:10 UTC (rev 7658)
+++ icecast/branches/kh/icecast/src/global.h	2004-08-29 15:17:14 UTC (rev 7659)
@@ -42,6 +42,10 @@
     /* relays retrieved from master */
     struct _relay_server *master_relays;
 
+    /* slave relay list */
+    unsigned int slave_count;
+    struct _slave_host *slaves;
+
     cond_t shutdown_cond;
 } ice_global_t;
 

Modified: icecast/branches/kh/icecast/src/slave.c
===================================================================
--- icecast/branches/kh/icecast/src/slave.c	2004-08-28 20:42:10 UTC (rev 7658)
+++ icecast/branches/kh/icecast/src/slave.c	2004-08-29 15:17:14 UTC (rev 7659)
@@ -60,10 +60,13 @@
 #define CATMODULE "slave"
 
 static void *_slave_thread(void *arg);
-thread_type *_slave_thread_id;
+static void _add_slave_host (const char *server, int port);
+
+static thread_type *_slave_thread_id;
 static int slave_running = 0;
 static unsigned int max_interval = 0;
 static int rescan_relays = 0;
+static rwlock_t slaves_lock;
 
 relay_server *relay_free (relay_server *relay)
 {
@@ -122,6 +125,7 @@
     if (slave_running)
         return;
 
+    thread_rwlock_create (&slaves_lock);
     slave_running = 1;
     _slave_thread_id = thread_create("Slave Thread", _slave_thread, NULL, THREAD_ATTACHED);
 }
@@ -134,20 +138,21 @@
     slave_running = 0;
     DEBUG0 ("waiting for slave thread");
     thread_join (_slave_thread_id);
+    thread_rwlock_destroy (&slaves_lock);
 }
 
 
 int slave_redirect (char *mountpoint, client_t *client)
 {
     slave_host *slave = NULL;
-    ice_config_t *c = config_get_config();
 
+    DEBUG1 ("slave count is %d", global.slave_count);
+    thread_rwlock_rlock (&slaves_lock);
     /* select slave entry */
-    if (c->slaves_count)
+    if (global.slave_count)
     {
-        int which=(int) (((float)c->slaves_count)*rand()/(RAND_MAX+1.0));
-        DEBUG1 ("which is %d", which);
-        slave = c->slave_list;
+        int which=(int) (((float)global.slave_count)*rand()/(RAND_MAX+1.0));
+        slave = global.slaves;
         while (slave && which)
         {
             slave = slave->next;
@@ -168,13 +173,13 @@
                     "at %s:%d", slave->server, slave->port);
             snprintf (location, len, "http://%s:%d%s", slave->server,
                     slave->port, mountpoint);
-            config_release_config();
+            thread_rwlock_unlock (&slaves_lock);
             client_send_302 (client, location);
             free (location);
             return 1;
         }
     }
-    config_release_config();
+    thread_rwlock_unlock (&slaves_lock);
     return 0;
 }
 
@@ -196,6 +201,7 @@
     do
     {
         char *auth_header;
+        char *redirect_header;
 
         streamsock = sock_connect_wto (relay->server, relay->port, 10);
         if (streamsock == SOCK_ERROR)
@@ -210,6 +216,7 @@
         {
             char *esc_authorisation;
             unsigned len = strlen(relay->username) + strlen(relay->password) + 2;
+            ice_config_t *config;
 
             auth_header = malloc (len);
             snprintf (auth_header, len, "%s:%s", relay->username, relay->password);
@@ -220,9 +227,23 @@
             snprintf (auth_header, len,
                     "Authorization: Basic %s\r\n", esc_authorisation);
             free(esc_authorisation);
+
+            /* header to use for participating in load sharing */
+            config = config_get_config ();
+            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);
+            }
+            config_release_config ();
         }
         else
+        {
             auth_header = strdup ("");
+            redirect_header = strdup ("");
+        }
 
         /* At this point we may not know if we are relaying an mp3 or vorbis
          * stream, but only send the icy-metadata header if the relay details
@@ -233,10 +254,14 @@
                 "User-Agent: " ICECAST_VERSION_STRING "\r\n"
                 "%s"
                 "%s"
+                "%s"
                 "\r\n",
-                relay->mount, relay->mp3metadata?"Icy-MetaData: 1\r\n":"",
+                relay->mount,
+                relay->mp3metadata?"Icy-MetaData: 1\r\n":"",
+                redirect_header,
                 auth_header);
         free (auth_header);
+        free (redirect_header);
         memset (header, 0, sizeof(header));
         if (util_read_header (con->sock, header, 4096) == 0)
         {
@@ -540,11 +565,38 @@
 }
 
 
+static void update_master_as_slave (ice_config_t *config)
+{
+    char *str;
+    slave_host *slave;
+
+    if (config->master_server == NULL || config->master_redirect_port == 0)
+        return;
+    str = strdup (config->master_server);
+    slave = calloc (1, sizeof(slave_host));
+    if (slave && str)
+    {
+        slave->server = str;
+        slave->port = config->master_server_port;
+        thread_rwlock_wlock (&slaves_lock);
+        _add_slave_host (config->master_server, config->master_server_port);
+        thread_rwlock_unlock (&slaves_lock);
+        return;
+    }
+    free (str);
+    free (slave);
+}
+
+
 static void *_slave_thread(void *arg)
 {
     ice_config_t *config;
     unsigned int interval = 0;
 
+    config = config_get_config();
+    update_master_as_slave (config);
+    config_release_config();
+
     while (slave_running)
     {
         relay_server *cleanup_relays;
@@ -561,6 +613,7 @@
 
             interval = 0;
             max_interval = config->master_update_interval;
+            update_master_as_slave (config);
 
             /* the connection could take some time, so the lock can drop */
             if (update_from_master (config))
@@ -594,3 +647,102 @@
     return NULL;
 }
 
+
+/* remove this slave clients entry in the slave host list */
+void slave_host_remove (client_t *client)
+{
+    const char *var = httpp_getvar (client->parser, "ice-redirect");
+
+    if (var)
+    {
+        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);
+    }
+}
+
+
+/* with the provided header (eg "localhost:8000") add a new slave host
+ * entry to so that clients can redirect to other sites when full
+ */
+void slave_host_add (client_t *client, const char *header)
+{
+    slave_host *slave;
+    char *server, *separator;
+    int port;
+
+    if (client == NULL || header == NULL)
+        return;
+
+    server = strdup (header);
+    separator = strchr (server, ':');
+    if (separator == NULL)
+    {
+        free (server);
+        return;
+    }
+    *separator = '\0';
+    port = atoi (separator+1);
+    thread_rwlock_wlock (&slaves_lock);
+    slave = global.slaves;
+    while (slave)
+    {
+        if (strcmp (slave->server, server) == 0 && slave->port == port)
+        {
+            slave->count++;
+            DEBUG0 ("already exists, increasing count");
+            break;
+        }
+        slave = slave->next;
+    }
+    if (slave == NULL)
+        _add_slave_host (server, port);
+    free (server);
+    thread_rwlock_unlock (&slaves_lock);
+}
+
+static void _add_slave_host (const char *server, int port)
+{
+    slave_host *slave = calloc (1, sizeof (slave_host));
+    if (slave == NULL)
+        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);
+}
+

Modified: icecast/branches/kh/icecast/src/slave.h
===================================================================
--- icecast/branches/kh/icecast/src/slave.h	2004-08-28 20:42:10 UTC (rev 7658)
+++ icecast/branches/kh/icecast/src/slave.h	2004-08-29 15:17:14 UTC (rev 7659)
@@ -36,6 +36,7 @@
 {
     char *server;
     int port;
+    unsigned int count;
     struct _slave_host *next;
 } slave_host;
 
@@ -44,6 +45,8 @@
 void slave_recheck (void);
 void slave_rescan (void);
 int slave_redirect (char *mountpoint, client_t *client);
+void slave_host_add (client_t *client, const char *header);
+void slave_host_remove (client_t *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	2004-08-28 20:42:10 UTC (rev 7658)
+++ icecast/branches/kh/icecast/src/source.c	2004-08-29 15:17:14 UTC (rev 7659)
@@ -885,8 +885,8 @@
     {
         if (connection_check_relay_pass(client->parser))
         {
+            client_as_slave (client);
             INFO0 ("client connected as slave");
-            client->is_slave = 1;
         }
         thread_mutex_lock (&move_clients_mutex);
         avl_tree_rlock (global.source_tree);



More information about the commits mailing list