[xiph-commits] r16154 - in icecast/branches/kh/icecast: . src

karl at svn.xiph.org karl at svn.xiph.org
Sun Jun 21 18:06:57 PDT 2009


Author: karl
Date: 2009-06-21 18:06:57 -0700 (Sun, 21 Jun 2009)
New Revision: 16154

Modified:
   icecast/branches/kh/icecast/configure.in
   icecast/branches/kh/icecast/src/admin.c
   icecast/branches/kh/icecast/src/auth.c
   icecast/branches/kh/icecast/src/auth.h
   icecast/branches/kh/icecast/src/auth_cmd.c
   icecast/branches/kh/icecast/src/auth_htpasswd.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/connection.h
   icecast/branches/kh/icecast/src/format.c
   icecast/branches/kh/icecast/src/format.h
   icecast/branches/kh/icecast/src/format_kate.c
   icecast/branches/kh/icecast/src/format_mp3.c
   icecast/branches/kh/icecast/src/global.c
   icecast/branches/kh/icecast/src/global.h
   icecast/branches/kh/icecast/src/refbuf.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/source.h
   icecast/branches/kh/icecast/src/stats.c
   icecast/branches/kh/icecast/src/yp.c
Log:
Various small updates collected. Most are down to code cleanups or shuffling functions
around.  Mainly to check in things not related to the thread update for kh10.


Modified: icecast/branches/kh/icecast/configure.in
===================================================================
--- icecast/branches/kh/icecast/configure.in	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/configure.in	2009-06-22 01:06:57 UTC (rev 16154)
@@ -1,4 +1,4 @@
-AC_INIT([Icecast], [2.3.2-kh9], [karl at xiph.org])
+AC_INIT([Icecast], [2.3.2-kh9b], [karl at xiph.org])
 
 AC_PREREQ(2.59)
 AC_CONFIG_SRCDIR(src/main.c)

Modified: icecast/branches/kh/icecast/src/admin.c
===================================================================
--- icecast/branches/kh/icecast/src/admin.c	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/admin.c	2009-06-22 01:06:57 UTC (rev 16154)
@@ -34,6 +34,7 @@
 #include "xslt.h"
 #include "fserve.h"
 #include "admin.h"
+#include "slave.h"
 
 #include "format.h"
 
@@ -157,7 +158,7 @@
         }
 
         thread_mutex_lock (&source->lock);
-        if (source->running || source->on_demand)
+        if (source_available (source))
         {
             ice_config_t *config;
             mount_proxy *mountinfo;
@@ -446,8 +447,8 @@
     source_t *dest;
     xmlDocPtr doc;
     xmlNodePtr node;
+    int parameters_passed = 0;
     char buf[255];
-    int parameters_passed = 0;
 
     if((COMMAND_OPTIONAL(client, "destination", dest_source))) {
         parameters_passed = 1;

Modified: icecast/branches/kh/icecast/src/auth.c
===================================================================
--- icecast/branches/kh/icecast/src/auth.c	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/auth.c	2009-06-22 01:06:57 UTC (rev 16154)
@@ -38,6 +38,13 @@
 #include "logging.h"
 #define CATMODULE "auth"
 
+struct _auth_thread_t
+{
+    thread_type *thread;
+    void *data;
+    unsigned int id;
+    struct auth_tag *auth;
+};
 
 static volatile int thread_id;
 
@@ -161,8 +168,8 @@
     }
     free (authenticator->handles);
 
-    if (authenticator->free)
-        authenticator->free (authenticator);
+    if (authenticator->release)
+        authenticator->release (authenticator);
     xmlFree (authenticator->type);
     xmlFree (authenticator->realm);
     thread_mutex_unlock (&authenticator->lock);
@@ -233,7 +240,7 @@
         }
     }
     if (auth_postprocess_listener (auth_user) < 0)
-        INFO1 ("client %lu failed", client->con->id);
+        INFO0 ("listener connection failed");
 }
 
 
@@ -346,189 +353,6 @@
 }
 
 
-/* Check whether this listener is on this source. This is only called when
- * there is auth. This may flag an existing listener to terminate.
- * return 1 if ok to add or 0 to prevent
- */
-static int check_duplicate_logins (source_t *source, client_t *client, auth_t *auth)
-{
-    client_t *existing;
-
-    if (auth == NULL || auth->allow_duplicate_users)
-        return 1;
-
-    /* allow multiple authenticated relays */
-    if (client->username == NULL || client->is_slave)
-        return 1;
-
-    existing = source->active_clients;
-    while (existing)
-    {
-        if (existing->con->error == 0 && existing->username &&
-                strcmp (existing->username, client->username) == 0)
-        {
-            if (auth->drop_existing_listener)
-            {
-                existing->con->error = 1;
-                return 1;
-            }
-            else
-                return 0;
-        }
-        existing = existing->next;
-    }
-    return 1;
-}
-
-
-/* Add client to source if it finds one. If a 0 is returned then the client should not be
- * touched, if the return value is -1 then it failed to add and should not be touched.
- * If it's a -2 value then the client is still around for any further processing.
- */
-static int add_listener_to_source (const char *mount, mount_proxy *mountinfo, client_t *client)
-{
-    int loop = 10;
-    int within_limits;
-    source_t *source;
-    mount_proxy *minfo = mountinfo;
-    const char *passed_mount = mount;
-    ice_config_t *config = config_get_config_unlocked();
-
-    do
-    {
-        int64_t stream_bitrate = 0;
-
-        do
-        {
-            source = source_find_mount_raw (mount);
-            if (loop == 0)
-            {
-                WARN0 ("preventing a fallback loop");
-                client_send_403 (client, "Fallback through too many mountpoints");
-                return -1;
-            }
-            if (source)
-            {
-                thread_mutex_lock (&source->lock);
-                if (source->running || source->on_demand)
-                    break;
-                thread_mutex_unlock (&source->lock);
-            }
-            if (minfo == NULL || minfo->fallback_mount == NULL)
-                return -2;
-            mount = minfo->fallback_mount;
-            minfo = config_find_mount (config_get_config_unlocked(), mount);
-            loop--;
-        } while (1);
-
-        /* ok, we found a source and it is locked */
-        if (client->is_slave)
-        {
-            if (source->client == NULL && source->on_demand == 0)
-            {
-                client_send_403 (client, "Slave relay reading from time unregulated stream");
-                return -1;
-            }
-            INFO0 ("client is from a slave, bypassing limits");
-            break;
-        }
-        if (source->format)
-        {
-            stream_bitrate  = 8 * rate_avg (source->format->in_bitrate);
-
-            if (config->max_bandwidth)
-            {
-                int64_t global_rate = (int64_t)8 * global_getrate_avg (global.out_bitrate);
-
-                DEBUG1 ("server outgoing bitrate is %" PRId64, global_rate);
-                if (global_rate + stream_bitrate > config->max_bandwidth)
-                {
-                    thread_mutex_unlock (&source->lock);
-                    INFO0 ("server-wide outgoing bandwidth limit reached");
-                    client_send_403redirect (client, passed_mount, "server bandwidth reached");
-                    return -1;
-                }
-            }
-        }
-
-        if (mountinfo == NULL)
-            break; /* allow adding listeners, no mount limits imposed */
-
-        if (check_duplicate_logins (source, client, mountinfo->auth) == 0)
-        {
-            thread_mutex_unlock (&source->lock);
-            client_send_403 (client, "Account already in use");
-            return -1;
-        }
-
-        /* set a per-mount disconnect time if auth hasn't set one already */
-        if (mountinfo->max_listener_duration && client->con->discon_time == 0)
-            client->con->discon_time = time(NULL) + mountinfo->max_listener_duration;
-
-        INFO3 ("max on %s is %ld (cur %lu)", source->mount,
-                mountinfo->max_listeners, source->listeners);
-
-        within_limits = 1;
-        if (mountinfo->max_bandwidth > -1 && stream_bitrate)
-        {
-            DEBUG3 ("checking bandwidth limits for %s (%" PRId64 ", %" PRId64 ")",
-                    mountinfo->mountname, stream_bitrate, mountinfo->max_bandwidth);
-            if ((source->listeners+1) * stream_bitrate > mountinfo->max_bandwidth)
-            {
-                INFO1 ("bandwidth limit reached on %s", source->mount);
-                within_limits = 0;
-            }
-        }
-        if (within_limits)
-        {
-            if (mountinfo->max_listeners == -1)
-                break;
-
-            if (source->listeners < (unsigned long)mountinfo->max_listeners)
-                break;
-            INFO1 ("max listener count reached on %s", source->mount);
-        }
-
-        /* minfo starts off as mountinfo put cascades through fallbacks */
-        if (minfo && minfo->fallback_when_full && minfo->fallback_mount)
-        {
-            thread_mutex_unlock (&source->lock);
-            mount = minfo->fallback_mount;
-            INFO1 ("stream full trying %s", mount);
-            loop--;
-            continue;
-        }
-
-        /* now we fail the client */
-        thread_mutex_unlock (&source->lock);
-        client_send_403redirect (client, passed_mount, "max listeners reached");
-        return -1;
-
-    } while (1);
-
-    client->write_to_client = format_generic_write_to_client;
-    client->check_buffer = format_check_http_buffer;
-    client->refbuf->len = PER_CLIENT_REFBUF_SIZE;
-    memset (client->refbuf->data, 0, PER_CLIENT_REFBUF_SIZE);
-
-    /* lets add the client to the active list */
-    client->next = source->active_clients;
-    source->active_clients = client;
-    source->listeners++;
-
-    thread_mutex_unlock (&source->lock);
-
-    if (source->running == 0 && source->on_demand)
-    {
-        /* enable on-demand relay to start, wake up the slave thread */
-        DEBUG0("kicking off on-demand relay");
-        source->on_demand_req = 1;
-    }
-    DEBUG1 ("Added client to %s", source->mount);
-    return 0;
-}
-
-
 /* Add listener to the pending lists of either the source or fserve thread. This can be run
  * from the connection or auth thread context. return -1 to indicate that client has been
  * terminated, 0 for receiving content.
@@ -568,7 +392,7 @@
     }
 
     avl_tree_rlock (global.source_tree);
-    ret = add_listener_to_source (mount, mountinfo, client);
+    ret = source_add_listener (mount, mountinfo, client);
     avl_tree_unlock (global.source_tree);
 
     if (ret == -2)
@@ -611,7 +435,6 @@
     mountinfo = config_find_mount (config, mount);
     ret = add_authenticated_listener (mount, mountinfo, client);
     config_release_config();
-
     auth_user->client = NULL;
 
     return ret;

Modified: icecast/branches/kh/icecast/src/auth.h
===================================================================
--- icecast/branches/kh/icecast/src/auth.h	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/auth.h	2009-06-22 01:06:57 UTC (rev 16154)
@@ -19,11 +19,11 @@
 
 struct source_tag;
 struct auth_tag;
+typedef struct _auth_thread_t auth_thread_t;
 
 #include <libxml/xmlmemory.h>
 #include <libxml/parser.h>
 #include <libxml/tree.h>
-#include "cfgfile.h"
 #include "client.h"
 #include "thread/thread.h"
 
@@ -52,14 +52,6 @@
 } auth_client;
 
 
-typedef struct _auth_thread_t
-{
-    thread_type *thread;
-    void *data;
-    unsigned int id;
-    struct auth_tag *auth;
-} auth_thread_t;
-
 typedef struct auth_tag
 {
     char *mount;
@@ -78,7 +70,7 @@
     void (*stream_end)(auth_client *auth_user);
 
     /* auth state-specific free call */
-    void (*free)(struct auth_tag *self);
+    void (*release)(struct auth_tag *self);
 
     /* call to allocate any per auth thread data */
     void *(*alloc_thread_data)(struct auth_tag *self);

Modified: icecast/branches/kh/icecast/src/auth_cmd.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_cmd.c	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/auth_cmd.c	2009-06-22 01:06:57 UTC (rev 16154)
@@ -123,7 +123,7 @@
     auth_cmd *state;
 
     authenticator->authenticate = auth_cmd_client;
-    authenticator->free = cmd_clear;
+    authenticator->release = cmd_clear;
     authenticator->adduser = auth_cmd_adduser;
     authenticator->deleteuser = auth_cmd_deleteuser;
     authenticator->listuser = auth_cmd_listuser;

Modified: icecast/branches/kh/icecast/src/auth_htpasswd.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_htpasswd.c	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/auth_htpasswd.c	2009-06-22 01:06:57 UTC (rev 16154)
@@ -181,8 +181,25 @@
     htpasswd_user entry;
     void *result;
 
-    if (client->username == NULL || client->password == NULL)
+    do {
+        const char *val;
+
+        if (client->username && client->password)
+            break;
+        free (client->username);
+        val = httpp_get_query_param (client->parser, "user");
+        if (val)
+        {
+            client->username = strdup (val);
+            val = httpp_get_query_param (client->parser, "pass");
+            if (val)
+            {
+                client->password = strdup (val);
+                break;
+            }
+        }
         return AUTH_FAILED;
+    } while (0);
 
     htpasswd_recheckfile (htpasswd);
 
@@ -216,7 +233,7 @@
     htpasswd_auth_state *state;
 
     authenticator->authenticate = htpasswd_auth;
-    authenticator->free = htpasswd_clear;
+    authenticator->release = htpasswd_clear;
     authenticator->adduser = htpasswd_adduser;
     authenticator->deleteuser = htpasswd_deleteuser;
     authenticator->listuser = htpasswd_userlist;

Modified: icecast/branches/kh/icecast/src/auth_url.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_url.c	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/auth_url.c	2009-06-22 01:06:57 UTC (rev 16154)
@@ -381,7 +381,7 @@
     if (res)
     {
         WARN2 ("auth to server %s failed with %s", url->addurl, atd->errormsg);
-        client_send_403 (client, "Unable to contact auth server");
+        client_send_403 (client, "Authentication not possible");
         auth_user->client = NULL;
         return AUTH_FAILED;
     }
@@ -586,7 +586,7 @@
 {
     auth_url *url_info;
 
-    authenticator->free = auth_url_clear;
+    authenticator->release = auth_url_clear;
     authenticator->adduser = auth_url_adduser;
     authenticator->deleteuser = auth_url_deleteuser;
     authenticator->listuser = auth_url_listuser;

Modified: icecast/branches/kh/icecast/src/cfgfile.c
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.c	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/cfgfile.c	2009-06-22 01:06:57 UTC (rev 16154)
@@ -975,6 +975,7 @@
         { "shoutcast-compat",   config_get_bool,    &listener->shoutcast_compat },
         { "bind-address",       config_get_str,     &listener->bind_address },
         { "queue-len",          config_get_int,     &listener->qlen },
+        { "so-sndbuf",          config_get_int,     &listener->so_sndbuf },
         { "ssl",                config_get_bool,    &listener->ssl },
         { "shoutcast-mount",    config_get_str,     &listener->shoutcast_mount },
         { NULL, NULL, NULL },

Modified: icecast/branches/kh/icecast/src/cfgfile.h
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.h	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/cfgfile.h	2009-06-22 01:06:57 UTC (rev 16154)
@@ -26,11 +26,9 @@
 struct ice_config_tag;
 typedef struct _listener_t listener_t;
 
-#include "thread/thread.h"
 #include "avl/avl.h"
 #include "auth.h"
 #include "global.h"
-#include "connection.h"
 
 typedef struct ice_config_dir_tag
 {
@@ -131,8 +129,37 @@
     int qlen;
     int shoutcast_compat;
     int ssl;
+    int so_sndbuf;
 };
 
+typedef struct _relay_server_master
+{
+    struct _relay_server_master *next;
+    char *ip;
+    char *bind;
+    char *mount;
+    int port;
+} relay_server_master;
+
+typedef struct _relay_server
+{
+    relay_server_master *masters;
+    char *username;
+    char *password;
+    char *localmount;
+    struct source_tag *source;
+    int interval;
+    int mp3metadata;
+    int on_demand;
+    int running;
+    int cleanup;
+    int enable;
+    time_t start;
+    thread_type *thread;
+    struct _relay_server *next;
+} relay_server;
+
+
 typedef struct
 {
     char *hostname;
@@ -264,7 +291,6 @@
 listener_t *config_clear_listener (listener_t *listener);
 void config_clear(ice_config_t *config);
 mount_proxy *config_find_mount (ice_config_t *config, const char *mount);
-listener_t *config_get_listen_sock (ice_config_t *config, sock_t serversock);
 
 int config_rehash(void);
 

Modified: icecast/branches/kh/icecast/src/client.c
===================================================================
--- icecast/branches/kh/icecast/src/client.c	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/client.c	2009-06-22 01:06:57 UTC (rev 16154)
@@ -36,11 +36,8 @@
 
 #include "client.h"
 #include "logging.h"
+#include "slave.h"
 
-#ifdef HAVE_AIO
-#include <errno.h>
-#endif
-
 #undef CATMODULE
 #define CATMODULE "client"
 
@@ -210,10 +207,10 @@
 {
     if (redirect_client (mount, client))
         return;
-    DEBUG0 ("dropping client");
     client_send_403 (client, reason);
 }
 
+
 void client_send_404(client_t *client, const char *message)
 {
     if (client->respcode)

Modified: icecast/branches/kh/icecast/src/client.h
===================================================================
--- icecast/branches/kh/icecast/src/client.h	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/client.h	2009-06-22 01:06:57 UTC (rev 16154)
@@ -18,13 +18,10 @@
 #ifndef __CLIENT_H__
 #define __CLIENT_H__
 
-#ifdef HAVE_AIO
-#include <aio.h>
-#endif
-
 struct source_tag;
 typedef struct _client_tag client_t;
 
+#include "cfgfile.h"
 #include "connection.h"
 #include "refbuf.h"
 #include "httpp/httpp.h"

Modified: icecast/branches/kh/icecast/src/connection.c
===================================================================
--- icecast/branches/kh/icecast/src/connection.c	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/connection.c	2009-06-22 01:06:57 UTC (rev 16154)
@@ -51,6 +51,7 @@
 #include "xslt.h"
 #include "fserve.h"
 #include "sighandler.h"
+#include "slave.h"
 
 #include "yp.h"
 #include "source.h"
@@ -85,10 +86,6 @@
     struct client_queue_tag *next;
 } client_queue_t;
 
-typedef struct _thread_queue_tag {
-    thread_type *thread_id;
-    struct _thread_queue_tag *next;
-} thread_queue_t;
 
 typedef struct
 {
@@ -1031,7 +1028,6 @@
 static void _handle_source_request (client_t *client, const char *uri)
 {
     INFO1("Source logging in at mountpoint \"%s\"", uri);
-
     if (uri[0] != '/')
     {
         WARN0 ("source mountpoint not starting with /");
@@ -1369,6 +1365,9 @@
                 sock_close (sock);
                 break;
             }
+            /* some win32 setups do not do TCP win scaling well, so allow an override */
+            if (listener->so_sndbuf)
+                sock_set_send_buffer (sock, listener->so_sndbuf);
             sock_set_blocking (sock, 0);
             successful = 1;
             global.serversock [count] = sock;
@@ -1416,3 +1415,4 @@
 #endif
     free(con);
 }
+

Modified: icecast/branches/kh/icecast/src/connection.h
===================================================================
--- icecast/branches/kh/icecast/src/connection.h	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/connection.h	2009-06-22 01:06:57 UTC (rev 16154)
@@ -26,7 +26,6 @@
 #include "cfgfile.h"
 #include "compat.h"
 #include "httpp/httpp.h"
-#include "thread/thread.h"
 #include "net/sock.h"
 
 struct connection_tag

Modified: icecast/branches/kh/icecast/src/format.c
===================================================================
--- icecast/branches/kh/icecast/src/format.c	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/format.c	2009-06-22 01:06:57 UTC (rev 16154)
@@ -44,9 +44,7 @@
 #include "stats.h"
 #define CATMODULE "format"
 
-static int format_prepare_headers (source_t *source, client_t *client);
 
-
 format_type_t format_get_type(const char *contenttype)
 {
     if(strcmp(contenttype, "application/x-ogg") == 0)
@@ -94,146 +92,25 @@
 }
 
 
-/* clients need to be start from somewhere in the queue so we will look for
- * a refbuf which has been previously marked as a sync point. 
- */
-static void find_client_start (source_t *source, client_t *client)
+int format_file_read (client_t *client, FILE *intro)
 {
-    refbuf_t *refbuf = source->burst_point;
-
-    /* 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
-            && source->stream_data_tail->sync_point)
-    {
-        refbuf = source->stream_data_tail;
-        client->lag = refbuf->len;
-    }
-    else
-    {
-        size_t size = client->intro_offset;
-        refbuf = source->burst_point;
-        client->lag = source->burst_offset;
-        while (size > 0 && refbuf && refbuf->next)
-        {
-            size -= refbuf->len;
-            client->lag -= refbuf->len;
-            refbuf = refbuf->next;
-        }
-    }
-
-    while (refbuf)
-    {
-        if (refbuf->sync_point)
-        {
-            client_set_queue (client, refbuf);
-            client->check_buffer = format_advance_queue;
-            client->write_to_client = source->format->write_buf_to_client;
-            client->intro_offset = -1;
-            break;
-        }
-        refbuf = refbuf->next;
-    }
-}
-
-
-static int get_file_data (FILE *intro, client_t *client)
-{
     refbuf_t *refbuf = client->refbuf;
-    size_t bytes;
 
-    if (intro == NULL || fseek (intro, client->intro_offset, SEEK_SET) < 0)
-        return 0;
-    bytes = fread (refbuf->data, 1, 4096, intro);
-    if (bytes == 0)
-        return 0;
-
-    refbuf->len = bytes;
-    return 1;
-}
-
-
-/* call to check the buffer contents for file reading. move the client
- * to right place in the queue at end of file else repeat file if queue
- * is not ready yet.
- */
-int format_check_file_buffer (source_t *source, client_t *client)
-{
-    refbuf_t *refbuf = client->refbuf;
-
-    if (refbuf == NULL)
-    {
-        /* client refers to no data, must be from a move */
-        if (source->client)
-        {
-            find_client_start (source, client);
-            return -1;
-        }
-        /* source -> file fallback, need a refbuf for data */
-        refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE);
-        client->refbuf = refbuf;
-        client->pos = refbuf->len;
-        client->intro_offset = 0;
-        client->lag = 0;
-    }
+    if (intro == NULL)
+        return -1;
     if (client->pos == refbuf->len)
     {
-        if (get_file_data (source->intro_file, client))
-        {
-            client->pos = 0;
-            client->intro_offset += refbuf->len;
-        }
-        else
-        {
-            if (source->stream_data_tail)
-            {
-                /* better find the right place in queue for this client */
-                client_set_queue (client, NULL);
-                find_client_start (source, client);
-            }
-            else
-                client->intro_offset = 0;  /* replay intro file */
-            return -1;
-        }
-    }
-    return 0;
-}
+        size_t bytes;
 
-
-/* call this to verify that the HTTP data has been sent and if so setup
- * callbacks to the appropriate format functions
- */
-int format_check_http_buffer (source_t *source, client_t *client)
-{
-    refbuf_t *refbuf = client->refbuf;
-
-    if (refbuf == NULL)
-        return -1;
-
-    if (client->respcode == 0)
-    {
-        DEBUG0("processing pending client headers");
-
-        if (format_prepare_headers (source, client) < 0)
-        {
-            ERROR0 ("internal problem, dropping client");
-            client->con->error = 1;
+        if (fseek (intro, client->intro_offset, SEEK_SET) < 0)
             return -1;
-        }
-        client->respcode = 200;
-        stats_event_inc (NULL, "listeners");
-        stats_event_inc (NULL, "listener_connections");
-        stats_event_inc (source->mount, "listener_connections");
-    }
+        bytes = fread (refbuf->data, 1, PER_CLIENT_REFBUF_SIZE, intro);
+        if (bytes == 0)
+            return -1;
 
-    if (client->pos == refbuf->len)
-    {
-        client->write_to_client = source->format->write_buf_to_client;
-        client->check_buffer = format_check_file_buffer;
-        client->intro_offset = 0;
-        client->pos = refbuf->len = 4096;
-        return -1;
+        client->intro_offset += bytes;
+        refbuf->len = bytes;
+        client->pos = 0;
     }
     return 0;
 }
@@ -246,6 +123,8 @@
     const char *buf = refbuf->data + client->pos;
     unsigned int len = refbuf->len - client->pos;
 
+    if (len > 4096) /* make sure we don't send huge amounts in one go */
+        len = 4096;
     ret = client_send_bytes (client, buf, len);
 
     if (ret > 0)
@@ -279,7 +158,7 @@
 }
 
 
-static int format_prepare_headers (source_t *source, client_t *client)
+int format_prepare_headers (source_t *source, client_t *client)
 {
     unsigned remaining;
     char *ptr;
@@ -288,6 +167,7 @@
     avl_node *node;
     ice_config_t *config;
 
+    DEBUG0 ("processing listener headers");
     remaining = client->refbuf->len;
     ptr = client->refbuf->data;
     client->respcode = 200;
@@ -374,7 +254,7 @@
     client->refbuf->len -= remaining;
     if (source->format->create_client_data)
         if (source->format->create_client_data (source, client) < 0)
-            return -1;
-    return 0;
+            bytes = -1;
+    return bytes;
 }
 

Modified: icecast/branches/kh/icecast/src/format.h
===================================================================
--- icecast/branches/kh/icecast/src/format.h	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/format.h	2009-06-22 01:06:57 UTC (rev 16154)
@@ -20,7 +20,6 @@
 
 #include "client.h"
 #include "refbuf.h"
-#include "httpp/httpp.h"
 
 struct source_tag;
 struct _mount_proxy;
@@ -64,9 +63,10 @@
 
 int format_generic_write_to_client (client_t *client);
 int format_advance_queue (struct source_tag *source, client_t *client);
-int format_check_http_buffer (struct source_tag *source, client_t *client);
-int format_check_file_buffer (struct source_tag *source, client_t *client);
 
+int format_file_read (client_t *client, FILE *fp);
+int format_prepare_headers (struct source_tag *source, client_t *client);
+
 void format_send_general_headers(format_plugin_t *format, 
         struct source_tag *source, client_t *client);
 

Modified: icecast/branches/kh/icecast/src/format_kate.c
===================================================================
--- icecast/branches/kh/icecast/src/format_kate.c	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/format_kate.c	2009-06-22 01:06:57 UTC (rev 16154)
@@ -152,25 +152,6 @@
     refbuf = make_refbuf_with_page (codec, page);
     /* DEBUG3 ("refbuf %p has pageno %ld, %llu", refbuf, ogg_page_pageno (page), (uint64_t)granulepos); */
 
-    if (codec->possible_start)
-    {
-        /* we don't bother trying to know where we can start, we'll just
-           start whenever we have to, video's more important and in the majority
-           of the cases it's ok if we lose an event we're seeking in the middle
-           of, as we won't have display artifacts as we'd have with video */
-        codec->possible_start->sync_point = 1;
-        refbuf_release (codec->possible_start);
-        codec->possible_start = NULL;
-    }
-    if (granulepos != kate->prev_granulepos || granulepos == 0)
-    {
-        if (codec->possible_start)
-            refbuf_release (codec->possible_start);
-        refbuf_addref (refbuf);
-        codec->possible_start = refbuf;
-    }
-    kate->prev_granulepos = granulepos;
-
     return refbuf;
 }
 

Modified: icecast/branches/kh/icecast/src/format_mp3.c
===================================================================
--- icecast/branches/kh/icecast/src/format_mp3.c	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/format_mp3.c	2009-06-22 01:06:57 UTC (rev 16154)
@@ -206,14 +206,14 @@
 
     if (mount)
     {
-        if (mount->mp3_meta_interval > 0)
+        if (mount->mp3_meta_interval >= 0)
             source_mp3->interval = mount->mp3_meta_interval;
         if (mount->charset)
             format->charset = strdup (mount->charset);
         if (mount->queue_block_size)
             source_mp3->queue_block_size = mount->queue_block_size;
     }
-    if (source_mp3->interval <= 0)
+    if (source_mp3->interval < 0)
     {
         const char *metadata = httpp_getvar (client->parser, "icy-metaint");
         source_mp3->interval = ICY_METADATA_INTERVAL;
@@ -467,7 +467,7 @@
 
     if (ret > 0)
         written += ret;
-    return written;
+    return written == 0 ? -1 : written;
 }
 
 static void format_mp3_free_plugin (format_plugin_t *plugin)
@@ -505,7 +505,6 @@
         source_mp3->read_count = 0;
     }
     buf = source_mp3->read_data->data + source_mp3->read_count;
-
     if (source_mp3->read_count < source_mp3->queue_block_size)
     {
         bytes = client_read_bytes (source->client, buf, source_mp3->queue_block_size-source_mp3->read_count);

Modified: icecast/branches/kh/icecast/src/global.c
===================================================================
--- icecast/branches/kh/icecast/src/global.c	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/global.c	2009-06-22 01:06:57 UTC (rev 16154)
@@ -19,7 +19,7 @@
 
 #include "thread/thread.h"
 #include "avl/avl.h"
-#include "httpp/httpp.h"
+#include "timing/timing.h"
 
 #include "connection.h"
 #include "refbuf.h"

Modified: icecast/branches/kh/icecast/src/global.h
===================================================================
--- icecast/branches/kh/icecast/src/global.h	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/global.h	2009-06-22 01:06:57 UTC (rev 16154)
@@ -23,8 +23,6 @@
 #define ICECAST_VERSION_STRING "Icecast " PACKAGE_VERSION
 
 #include "thread/thread.h"
-#include "slave.h"
-#include "timing/timing.h"
 #include "net/sock.h"
 
 typedef struct ice_global_tag

Modified: icecast/branches/kh/icecast/src/refbuf.h
===================================================================
--- icecast/branches/kh/icecast/src/refbuf.h	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/refbuf.h	2009-06-22 01:06:57 UTC (rev 16154)
@@ -19,7 +19,6 @@
 #define __REFBUF_H__
 
 #include <sys/types.h>
-#include "compat.h"
 
 typedef struct _refbuf_tag
 {

Modified: icecast/branches/kh/icecast/src/slave.c
===================================================================
--- icecast/branches/kh/icecast/src/slave.c	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/slave.c	2009-06-22 01:06:57 UTC (rev 16154)
@@ -309,14 +309,14 @@
             bind = master->bind;
 
         if (bind)
-            INFO3 ("connecting to %s:%d, bound to %s", server, port, bind);
+            INFO4 ("connecting to %s:%d for %s, bound to %s", server, port, relay->localmount, bind);
         else
-            INFO2 ("connecting to %s:%d", server, port);
+            INFO3 ("connecting to %s:%d for %s", server, port, relay->localmount);
 
         streamsock = sock_connect_wto_bind (server, port, bind, 10);
         if (streamsock == SOCK_ERROR)
         {
-            WARN2 ("Failed to connect to %s:%d", server, port);
+            WARN3 ("Failed to connect to %s:%d for %s", server, port, relay->localmount);
             break;
         }
         con = connection_create (streamsock, SOCK_ERROR, strdup (server));

Modified: icecast/branches/kh/icecast/src/slave.h
===================================================================
--- icecast/branches/kh/icecast/src/slave.h	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/slave.h	2009-06-22 01:06:57 UTC (rev 16154)
@@ -13,43 +13,15 @@
 #ifndef __SLAVE_H__
 #define __SLAVE_H__
 
-#include "thread/thread.h"
+#include "client.h"
 
-struct _client_tag;
-
-typedef struct _relay_server_master {
-    struct _relay_server_master *next;
-    char *ip;
-    char *bind;
-    char *mount;
-    int port;
-} relay_server_master;
-
-typedef struct _relay_server {
-    relay_server_master *masters;
-    char *username;
-    char *password;
-    char *localmount;
-    struct source_tag *source;
-    int interval;
-    int mp3metadata;
-    int on_demand;
-    int running;
-    int cleanup;
-    int enable;
-    time_t start;
-    thread_type *thread;
-    struct _relay_server *next;
-} relay_server;
-
-
 void slave_initialize(void);
 void slave_shutdown(void);
 void slave_restart (void);
 void slave_update_all_mounts (void);
 void slave_rebuild_mounts (void);
 relay_server *slave_find_relay (relay_server *relays, const char *mount);
-int redirect_client (const char *mountpoint, 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);
 

Modified: icecast/branches/kh/icecast/src/source.c
===================================================================
--- icecast/branches/kh/icecast/src/source.c	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/source.c	2009-06-22 01:06:57 UTC (rev 16154)
@@ -27,7 +27,6 @@
 
 #ifndef _WIN32
 #include <unistd.h>
-#include <sys/time.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
 #else
@@ -36,6 +35,7 @@
 #endif
 
 #include "thread/thread.h"
+#include "timing/timing.h"
 #include "avl/avl.h"
 #include "httpp/httpp.h"
 #include "net/sock.h"
@@ -53,6 +53,7 @@
 #include "fserve.h"
 #include "auth.h"
 #include "compat.h"
+#include "slave.h"
 
 #undef CATMODULE
 #define CATMODULE "source"
@@ -62,10 +63,15 @@
 mutex_t move_clients_mutex;
 
 /* avl tree helper */
-static int _compare_clients(void *compare_arg, void *a, void *b);
+static int  _compare_clients(void *compare_arg, void *a, void *b);
 static void _parse_audio_info (source_t *source, const char *s);
 static void source_shutdown (source_t *source);
 static void process_listeners (source_t *source, int fast_clients_only, int deletion_expected);
+
+static int  http_source_listener (source_t *source, client_t *client);
+static int  http_source_intro (source_t *source, client_t *client);
+static int  locate_start_on_queue (source_t *source, client_t *client);
+
 #ifdef _WIN32
 #define source_run_script(x,y)  WARN0("on [dis]connect scripts disabled");
 #else
@@ -127,7 +133,7 @@
     
     while (node) {
         source = (source_t *)node->key;
-        cmp = strcmp(mount, source->mount);
+        cmp = strcmp (mount, source->mount);
         if (cmp < 0) 
             node = node->left;
         else if (cmp > 0)
@@ -155,11 +161,11 @@
     config = config_get_config();
     while (mount && depth < MAX_FALLBACK_DEPTH)
     {
-        source = source_find_mount_raw(mount);
+        source = source_find_mount_raw (mount);
 
         if (source)
         {
-            if (source->running || source->on_demand)
+            if (source_available (source))
                 break;
         }
 
@@ -231,7 +237,6 @@
         auth_release_listener (client, source->mount, mountinfo);
     }
     config_release_config ();
-
     if (i)
         stats_event_sub (NULL, "listeners", i);
 
@@ -331,7 +336,6 @@
             break;
         client = client->next;
     }
-
     return client;
 }
 
@@ -399,10 +403,10 @@
              * refbuf it's referring to, if it's http headers then we need
              * to write them so don't release it.
              */
-            if (client->check_buffer != format_check_http_buffer)
+            if (client->check_buffer != http_source_listener)
             {
                 client_set_queue (client, NULL);
-                client->check_buffer = format_check_file_buffer;
+                client->check_buffer = http_source_intro;
                 if (source->client == NULL)
                     client->intro_offset = -1;
             }
@@ -632,6 +636,126 @@
 }
 
 
+static int locate_start_on_queue (source_t *source, client_t *client)
+{
+    refbuf_t *refbuf;
+    long lag = 0;
+    int ret = -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 (source->stream_data_tail == NULL)
+        return -1;
+    refbuf = source->stream_data_tail;
+    DEBUG0 ("in here");
+    if (client->intro_offset == -1 && refbuf->sync_point)
+    {
+        refbuf = source->stream_data_tail;
+        lag = refbuf->len;
+    }
+    else
+    {
+        size_t size = client->intro_offset;
+        refbuf = source->burst_point;
+        lag = source->burst_offset;
+        while (size > 0 && refbuf && refbuf->next)
+        {
+            size -= refbuf->len;
+            lag -= refbuf->len;
+            refbuf = refbuf->next;
+        }
+        if (lag < 0)
+            ERROR1 ("Odd, lag is negative", lag);
+    }
+
+    while (refbuf)
+    {
+        if (refbuf->sync_point)
+        {
+            client_set_queue (client, refbuf);
+            client->check_buffer = format_advance_queue;
+            client->write_to_client = source->format->write_buf_to_client;
+            client->intro_offset = -1;
+            client->lag = lag;
+            ret = 0;
+            break;
+        }
+        lag -= refbuf->len;
+        refbuf = refbuf->next;
+    }
+    return ret;
+}
+
+
+static int http_source_intro (source_t *source, client_t *client)
+{
+    refbuf_t *refbuf = client->refbuf;
+
+    if (refbuf == NULL)
+    {
+        /* client refers to no data, must be from a move */
+        if (source->client)
+        {
+            locate_start_on_queue (source, client);
+            return -1;
+        }
+        /* source -> file fallback, need a refbuf for data */
+        refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE);
+        client->refbuf = refbuf;
+        client->pos = refbuf->len;
+        client->intro_offset = 0;
+        client->lag = 0;
+    }
+    if (format_file_read (client, source->intro_file) < 0)
+    {
+        if (source->stream_data_tail)
+        {
+            /* better find the right place in queue for this client */
+            client_set_queue (client, NULL);
+            return locate_start_on_queue (source, client);
+        }
+        client->intro_offset = 0;  /* replay intro file */
+        return -1;
+    }
+    return 0;
+}
+
+
+static int http_source_listener (source_t *source, client_t *client)
+{
+    refbuf_t *refbuf = client->refbuf;
+
+    if (refbuf == NULL)
+        return -1;
+
+    if (client->respcode == 0)
+    {
+        DEBUG0("processing pending listener headers");
+
+        if (format_prepare_headers (source, client) < 0)
+        {
+            ERROR0 ("internal problem, dropping client");
+            client->con->error = 1;
+            return -1;
+        }
+        client->respcode = 200;
+        stats_event_inc (NULL, "listeners");
+        stats_event_inc (NULL, "listener_connections");
+        stats_event_inc (source->mount, "listener_connections");
+    }
+    if (client->pos == refbuf->len)
+    {
+        client->write_to_client = source->format->write_buf_to_client;
+        client->check_buffer = http_source_intro;
+        client->intro_offset = 0;
+        client->pos = refbuf->len = 4096;
+        return -1;
+    }
+    return 0;
+}
+
+
 /* general send routine per listener.  The deletion_expected tells us whether
  * the last in the queue is about to disappear, so if this client is still
  * referring to it after writing then drop the client as it's fallen too far
@@ -643,7 +767,7 @@
 static int send_to_listener (source_t *source, client_t *client, int deletion_expected)
 {
     int bytes;
-    int loop = 10;   /* max number of iterations in one go */
+    int loop = 8;   /* max number of iterations in one go */
     long total_written = 0;
     int ret = 0;
 
@@ -748,7 +872,7 @@
             continue;
         }
         listener_count++;
-        if (fast_client && client->check_buffer != format_check_file_buffer)
+        if (fast_client && client->check_buffer != http_source_intro)
         {
             client_t *to_move = client;
 
@@ -827,7 +951,6 @@
     stats_event_hidden (source->mount, "total_bytes_sent", "0", STATS_COUNTERS);
     stats_event_hidden (source->mount, "total_bytes_read", "0", STATS_COUNTERS);
 
-    DEBUG0("Source creation complete");
     source->last_read = time(NULL);
     source->prev_listeners = -1;
     source->bytes_sent_since_update = 0;
@@ -886,6 +1009,7 @@
 
     source->format->in_bitrate = rate_setup (source->avg_bitrate_duration+1, 1);
     source->format->out_bitrate = rate_setup (120, 1000);
+    INFO1 ("Source %s initialised", source->mount);
     source->running = 1;
 }
 
@@ -1280,6 +1404,9 @@
     if (mountinfo && mountinfo->burst_size >= 0)
         source->burst_size = (unsigned int)mountinfo->burst_size;
 
+    if (source->burst_size > source->queue_size_limit - 50000)
+        source->queue_size_limit = source->burst_size + 50000;
+
     source->wait_time = 0;
     if (mountinfo && mountinfo->wait_time)
         source->wait_time = (time_t)mountinfo->wait_time;
@@ -1577,6 +1704,186 @@
 }
 
 
+/* Check whether this listener is on this source. This is only called when
+ * there is auth. This may flag an existing listener to terminate.
+ * return 1 if ok to add or 0 to prevent
+ */
+static int check_duplicate_logins (source_t *source, client_t *client, auth_t *auth)
+{
+    client_t *existing;
+
+    if (auth == NULL || auth->allow_duplicate_users)
+        return 1;
+
+    /* allow multiple authenticated relays */
+    if (client->username == NULL || client->is_slave)
+        return 1;
+
+    existing = source->active_clients;
+    while (existing)
+    {
+        if (existing->con->error == 0 && existing->username &&
+                strcmp (existing->username, client->username) == 0)
+        {
+            if (auth->drop_existing_listener)
+            {
+                existing->con->error = 1;
+                return 1;
+            }
+            else
+                return 0;
+        }
+        existing = existing->next;
+    }
+    return 1;
+}
+
+
+/* Add client to source if it finds one. If a 0 is returned then the client should not be
+ * touched, if the return value is -1 then it failed to add and should not be touched.
+ * If it's a -2 value then the client is still around for any further processing.
+ */
+int source_add_listener (const char *mount, mount_proxy *mountinfo, client_t *client)
+{
+    int loop = 10;
+    int within_limits;
+    source_t *source;
+    mount_proxy *minfo = mountinfo;
+    const char *passed_mount = mount;
+    ice_config_t *config = config_get_config_unlocked();
+
+    do
+    {
+        int64_t stream_bitrate = 0;
+
+        do
+        {
+            source = source_find_mount_raw (mount);
+            if (loop == 0)
+            {
+                WARN0 ("preventing a fallback loop");
+                client_send_403 (client, "Fallback through too many mountpoints");
+                return -1;
+            }
+            if (source)
+            {
+                thread_mutex_lock (&source->lock);
+                if (source_available (source))
+                    break;
+                thread_mutex_unlock (&source->lock);
+            }
+            if (minfo == NULL || minfo->fallback_mount == NULL)
+                return -2;
+            mount = minfo->fallback_mount;
+            minfo = config_find_mount (config_get_config_unlocked(), mount);
+            loop--;
+        } while (1);
+
+        /* ok, we found a source and it is locked */
+        if (client->is_slave)
+        {
+            if (source->client == NULL && source->on_demand == 0)
+            {
+                client_send_403 (client, "Slave relay reading from time unregulated stream");
+                return -1;
+            }
+            INFO0 ("client is from a slave, bypassing limits");
+            break;
+        }
+        if (source->format)
+        {
+            stream_bitrate  = 8 * rate_avg (source->format->in_bitrate);
+
+            if (config->max_bandwidth)
+            {
+                int64_t global_rate = (int64_t)8 * global_getrate_avg (global.out_bitrate);
+
+                DEBUG1 ("server outgoing bitrate is %" PRId64, global_rate);
+                if (global_rate + stream_bitrate > config->max_bandwidth)
+                {
+                    thread_mutex_unlock (&source->lock);
+                    INFO0 ("server-wide outgoing bandwidth limit reached");
+                    client_send_403redirect (client, passed_mount, "server bandwidth reached");
+                    return -1;
+                }
+            }
+        }
+
+        if (mountinfo == NULL)
+            break; /* allow adding listeners, no mount limits imposed */
+
+        if (check_duplicate_logins (source, client, mountinfo->auth) == 0)
+        {
+            thread_mutex_unlock (&source->lock);
+            client_send_403 (client, "Account already in use");
+            return -1;
+        }
+
+        /* set a per-mount disconnect time if auth hasn't set one already */
+        if (mountinfo->max_listener_duration && client->con->discon_time == 0)
+            client->con->discon_time = time(NULL) + mountinfo->max_listener_duration;
+
+        INFO3 ("max on %s is %ld (cur %lu)", source->mount,
+                mountinfo->max_listeners, source->listeners);
+        within_limits = 1;
+        if (mountinfo->max_bandwidth > -1 && stream_bitrate)
+        {
+            DEBUG3 ("checking bandwidth limits for %s (%" PRId64 ", %" PRId64 ")",
+                    mountinfo->mountname, stream_bitrate, mountinfo->max_bandwidth);
+            if ((source->listeners+1) * stream_bitrate > mountinfo->max_bandwidth)
+            {
+                INFO1 ("bandwidth limit reached on %s", source->mount);
+                within_limits = 0;
+            }
+        }
+        if (within_limits)
+        {
+            if (mountinfo->max_listeners == -1)
+                break;
+
+            if (source->listeners < (unsigned long)mountinfo->max_listeners)
+                break;
+            INFO1 ("max listener count reached on %s", source->mount);
+        }
+        /* minfo starts off as mountinfo put cascades through fallbacks */
+        if (minfo && minfo->fallback_when_full && minfo->fallback_mount)
+        {
+            thread_mutex_unlock (&source->lock);
+            mount = minfo->fallback_mount;
+            INFO1 ("stream full trying %s", mount);
+            loop--;
+            continue;
+        }
+
+        /* now we fail the client */
+        thread_mutex_unlock (&source->lock);
+        client_send_403redirect (client, passed_mount, "max listeners reached");
+        return -1;
+
+    } while (1);
+
+    client->con->sent_bytes = 0;
+    client->write_to_client = format_generic_write_to_client;
+    client->check_buffer = http_source_listener;
+    client->refbuf->len = PER_CLIENT_REFBUF_SIZE;
+    memset (client->refbuf->data, 0, PER_CLIENT_REFBUF_SIZE);
+
+    /* lets add the client to the active list */
+    client->next = source->active_clients;
+    source->active_clients = client;
+    source->listeners++;
+    thread_mutex_unlock (&source->lock);
+
+    if (source->running == 0 && source->on_demand)
+    {
+        /* enable on-demand relay to start, wake up the slave thread */
+        DEBUG0("kicking off on-demand relay");
+        source->on_demand_req = 1;
+    }
+    return 0;
+}
+
+
 void source_startup (client_t *client, const char *uri)
 {
     source_t *source;

Modified: icecast/branches/kh/icecast/src/source.h
===================================================================
--- icecast/branches/kh/icecast/src/source.h	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/source.h	2009-06-22 01:06:57 UTC (rev 16154)
@@ -86,6 +86,8 @@
 
 } source_t;
 
+#define source_available(x)     ((x)->running || (x)->on_demand)
+
 source_t *source_reserve (const char *mount);
 void *source_client_thread (void *arg);
 void source_startup (client_t *client, const char *uri);
@@ -101,6 +103,7 @@
 int source_remove_client(void *key);
 void source_main(source_t *source);
 void source_recheck_mounts (int update_all);
+int  source_add_listener (const char *mount, mount_proxy *mountinfo, client_t *client);
 
 extern mutex_t move_clients_mutex;
 

Modified: icecast/branches/kh/icecast/src/stats.c
===================================================================
--- icecast/branches/kh/icecast/src/stats.c	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/stats.c	2009-06-22 01:06:57 UTC (rev 16154)
@@ -511,7 +511,6 @@
                 node->hidden = event->hidden;
                 if (snode->hidden & STATS_HIDDEN)
                     node->hidden |= STATS_HIDDEN;
-
                 stats_listener_send (node->hidden, "EVENT %s %s %s\n", event->source, event->name, event->value);
                 avl_insert(snode->stats_tree, (void *)node);
             }
@@ -525,6 +524,7 @@
             return;
         }
         modify_node_event (node, event);
+        stats_listener_send (node->hidden, "EVENT %s %s %s\n", event->source, node->name, node->value);
         return;
     }
     /* change source hidden status */
@@ -561,11 +561,7 @@
         return;
     }
     if (event->action == STATS_EVENT_REMOVE)
-    {
-        DEBUG1 ("delete source node %s", event->source);
-        stats_listener_send (snode->hidden, "DELETE %s\n", event->source);
         avl_delete(_stats.source_tree, (void *)snode, _free_source_stats);
-    }
 }
 
 
@@ -698,6 +694,8 @@
     va_list vl;
 
     va_copy (vl, ap);
+    if (len <= 0)
+        return -1;
     ret = vsnprintf (buf, len, fmt, vl);
     if (ret < 0 || ret >= len)
         return -1;
@@ -719,9 +717,12 @@
 
 static void _add_node_to_stats_client (event_listener_t *listener, refbuf_t *refbuf)
 {
-    *listener->queue_recent_p = refbuf;
-    listener->queue_recent_p = &refbuf->next;
-    listener->content_len += refbuf->len;
+    if (refbuf->len) 
+    {
+        *listener->queue_recent_p = refbuf;
+        listener->queue_recent_p = &refbuf->next;
+        listener->content_len += refbuf->len;
+    }
 }
 
 
@@ -803,69 +804,61 @@
     stats_count.action = STATS_EVENT_INC;
     process_event_unlocked (&stats_count);
 
-    while (size < 50000)    /* use a large limit */
+    /* first we fill our queue with the current stats */
+    refbuf = refbuf_new (size);
+    refbuf->len = 0;
+
+    /* the global stats */
+    node = avl_get_first(_stats.global_tree);
+    while (node)
     {
-        /* first we fill our queue with the current stats */
-        refbuf = refbuf_new (size);
-        refbuf->len = 0;
+        stats_node_t *stat = node->key;
 
-        /* starts with the http response header */
-        if (_append_to_buffer (refbuf, size, "HTTP/1.0 200 OK\r\ncapability: streamlist\r\n\r\n") < 0)
+        if (stat->hidden & listener->hidden_level)
         {
-            refbuf_release (refbuf);
-            break;
-        }
-        /* now the global stats */
-        node = avl_get_first(_stats.global_tree);
-        while (node)
-        {
-            stats_node_t *stat = node->key;
-
-            node = avl_get_next(node);
-            if ((stat->hidden & listener->hidden_level) == 0)
-                continue;
             if (_append_to_buffer (refbuf, size, "EVENT global %s %s\n", stat->name, stat->value) < 0)
             {
-                size += 8192;
-                refbuf_release (refbuf);
-                break;
+                _add_node_to_stats_client (listener, refbuf);
+                refbuf = refbuf_new (size);
+                refbuf->len = 0;
+                continue;
             }
         }
-        if (node) continue; /* catch buffer full case */
-
-        /* now the stats for each source */
-        node = avl_get_first(_stats.source_tree);
-        while (node)
+        node = avl_get_next(node);
+    }
+    /* now the stats for each source */
+    node = avl_get_first(_stats.source_tree);
+    while (node)
+    {
+        avl_node *node2;
+        stats_source_t *snode = (stats_source_t *)node->key;
+        if (snode->hidden & listener->hidden_level)
         {
-            avl_node *node2;
-            stats_source_t *snode = (stats_source_t *)node->key;
-            node = avl_get_next(node);
-            if ((snode->hidden & listener->hidden_level) == 0)
-                continue;
             if (_append_to_buffer (refbuf, size, "NEW %s\n", snode->source) < 0)
             {
-                size += 8192;
-                refbuf_release (refbuf);
-                break;
+                _add_node_to_stats_client (listener, refbuf);
+                refbuf = refbuf_new (size);
+                refbuf->len = 0;
+                continue;
             }
-            node2 = avl_get_first(snode->stats_tree);
-            while (node2)
+        }
+        node = avl_get_next(node);
+        node2 = avl_get_first(snode->stats_tree);
+        while (node2)
+        {
+            stats_node_t *stat = node2->key;
+            if (stat->hidden & listener->hidden_level)
             {
-                stats_node_t *stat = node2->key;
-                node2 = avl_get_next(node2);
-
-                if ((stat->hidden & listener->hidden_level) == 0)
-                    continue;
                 if (_append_to_buffer (refbuf, size, "EVENT %s %s %s\n", snode->source, stat->name, stat->value) < 0)
                 {
-                    size += 8192;
-                    refbuf_release (refbuf);
-                    break;
+                    _add_node_to_stats_client (listener, refbuf);
+                    refbuf = refbuf_new (size);
+                    refbuf->len = 0;
+                    continue;
                 }
             }
+            node2 = avl_get_next (node2);
         }
-        if (node) continue; /* catch buffer full case */
-        break;
     }
 
     client_set_queue (listener->client, refbuf);
@@ -896,7 +889,9 @@
     listener->queue_recent_p = &listener->queue;
 
     client->respcode = 200;
-    snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
+    client_set_queue (client, NULL);
+    client->refbuf = refbuf_new (100);
+    snprintf (client->refbuf->data, 100,
             "HTTP/1.0 200 OK\r\ncapability: streamlist\r\n\r\n");
     client->refbuf->len = strlen (client->refbuf->data);
     fserve_add_client_callback (client, stats_callback, listener);
@@ -971,6 +966,8 @@
 static int _free_source_stats(void *key)
 {
     stats_source_t *node = (stats_source_t *)key;
+    stats_listener_send (node->hidden, "DELETE %s\n", node->source);
+    DEBUG1 ("delete source node %s", node->source);
     avl_tree_free(node->stats_tree, _free_stats);
     free(node->source);
     free(node);
@@ -1049,7 +1046,6 @@
         {
             /* no source_t is reserved so remove them now */
             snode = avl_get_next (snode);
-            DEBUG1 ("releasing %s stats", src->source);
             avl_delete (_stats.source_tree, src, _free_source_stats);
             continue;
         }

Modified: icecast/branches/kh/icecast/src/yp.c
===================================================================
--- icecast/branches/kh/icecast/src/yp.c	2009-06-21 17:28:50 UTC (rev 16153)
+++ icecast/branches/kh/icecast/src/yp.c	2009-06-22 01:06:57 UTC (rev 16154)
@@ -296,7 +296,7 @@
     if (curlcode)
     {
         yp->process = do_yp_add;
-        yp->next_update += 1200;
+        yp->next_update = now + 1200;
         ERROR2 ("connection to %s failed with \"%s\"", server->url, server->curl_error);
         return -2;
     }
@@ -307,7 +307,7 @@
         if (yp->process == do_yp_add)
         {
             ERROR3 ("YP %s on %s failed: %s", cmd, server->url, yp->error_msg);
-            yp->next_update += 7200;
+            yp->next_update = now + 7200;
         }
         if (yp->process == do_yp_touch)
         {
@@ -318,9 +318,9 @@
              * cases as a firewall block or incorrect listenurl.
              */
             if (yp->touch_interval < 1200)
-                yp->next_update += 1200;
+                yp->next_update = now + 1200;
             else
-                yp->next_update += yp->touch_interval;
+                yp->next_update = now + yp->touch_interval;
             INFO3 ("YP %s on %s failed: %s", cmd, server->url, yp->error_msg);
         }
         yp->process = do_yp_add;
@@ -408,7 +408,7 @@
     {
         yp->process = do_yp_touch;
         /* force first touch in 5 secs */
-        yp->next_update = time(NULL) + 5;
+        yp->next_update = now + 5;
     }
     return ret;
 }



More information about the commits mailing list