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

karl at svn.xiph.org karl at svn.xiph.org
Tue Aug 3 17:59:21 PDT 2010


Author: karl
Date: 2010-08-03 17:59:21 -0700 (Tue, 03 Aug 2010)
New Revision: 17362

Modified:
   icecast/branches/kh/icecast/NEWS
   icecast/branches/kh/icecast/config.h.vc6
   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/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/flv.c
   icecast/branches/kh/icecast/src/format_mp3.c
   icecast/branches/kh/icecast/src/format_ogg.c
   icecast/branches/kh/icecast/src/fserve.c
   icecast/branches/kh/icecast/src/mpeg.c
   icecast/branches/kh/icecast/src/mpeg.h
   icecast/branches/kh/icecast/src/slave.c
   icecast/branches/kh/icecast/src/source.c
   icecast/branches/kh/icecast/src/util.c
   icecast/branches/kh/icecast/src/yp.c
   icecast/branches/kh/icecast/win32/icecast.dsp
   icecast/branches/kh/icecast/win32/icecast2.iss
Log:
kh25. worker thread update (reduces locking), client schedule tuning, build
cleanups, a couple of odd case crash fixes


Modified: icecast/branches/kh/icecast/NEWS
===================================================================
--- icecast/branches/kh/icecast/NEWS	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/NEWS	2010-08-04 00:59:21 UTC (rev 17362)
@@ -16,6 +16,27 @@
 any extra tags are show in the conf/icecast.xml.dist file
 
 
+2.3.2-kh25
+. FLV clients could skip frames on a truncated write, leading to playback problems.
+. various client scheduling tunings, allows quicker reschedule when only some data
+  was written. This seems to affect win32 more than others, especially with burst
+. fix shoutcast-inline metadata bug involving a URL
+. per listener mpeg checking only verifies 1 frame as queue is already checked
+. set non-ogg intial blocksize to 1400 again, now that blocks can be more flexible
+  in size
+. filter out multiple / in requests
+. the 2.3 log archive setting wasn't handled correctly.
+. certain relay configuration (multiple addresses) could leak a file descriptor
+  on failure.
+. possible NULL pointer crash in metadata update.
+. possible sources count not decreased if relay fails.
+. fix for possible relay change restart
+. worker lock changes, now we only take the lock when adding clients. This reduces
+  some lock order complexity when moving clients around and means that no locking
+  is done for most of the time.
+. relay changes are tagged and changed by the client functions.
+. compile cleanups
+
 2.3.2-kh24
 . Allow for per-listener wrapping of existing mp3/aac streams when requested with
   a type=.flv as a query arg. The actual trigger could be anything we want but this

Modified: icecast/branches/kh/icecast/config.h.vc6
===================================================================
--- icecast/branches/kh/icecast/config.h.vc6	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/config.h.vc6	2010-08-04 00:59:21 UTC (rev 17362)
@@ -95,7 +95,7 @@
 #define PACKAGE_NAME "Icecast"
 
 /* Version number of package */
-#define VERSION "2.3.2-kh24"
+#define VERSION "2.3.2-kh25"
 
 /* Define to the version of this package. */
 #define PACKAGE_VERSION VERSION
@@ -136,6 +136,7 @@
 #define vsnprintf _vsnprintf
 #define getpid _getpid
 #define atoll _atoi64
+#define pipe(x) _pipe(x,255,O_BINARY)
 
 #define fseeko fseek
 #define PRIdMAX "ld"

Modified: icecast/branches/kh/icecast/configure.in
===================================================================
--- icecast/branches/kh/icecast/configure.in	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/configure.in	2010-08-04 00:59:21 UTC (rev 17362)
@@ -1,4 +1,4 @@
-AC_INIT([Icecast], [2.3.2-kh24], [karl at xiph.org])
+AC_INIT([Icecast], [2.3.2-kh25], [karl at xiph.org])
 
 LT_INIT
 AC_PREREQ(2.59)

Modified: icecast/branches/kh/icecast/src/admin.c
===================================================================
--- icecast/branches/kh/icecast/src/admin.c	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/admin.c	2010-08-04 00:59:21 UTC (rev 17362)
@@ -1040,9 +1040,10 @@
     COMMAND_OPTIONAL(client, "charset", charset);
 
     plugin = source->format;
-    if (source->client && strcmp (client->connection.ip, source->client->connection.ip) != 0)
-        if (response == RAW && connection_check_admin_pass (client->parser) == 0)
-            same_ip = 0;
+    if (source_running (source))
+        if (strcmp (client->connection.ip, source->client->connection.ip) != 0)
+            if (response == RAW && connection_check_admin_pass (client->parser) == 0)
+                same_ip = 0;
 
     do
     {

Modified: icecast/branches/kh/icecast/src/auth.c
===================================================================
--- icecast/branches/kh/icecast/src/auth.c	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/auth.c	2010-08-04 00:59:21 UTC (rev 17362)
@@ -351,9 +351,7 @@
                 if (worker)
                 {
                     /* wakeup worker for new client */
-                    thread_mutex_lock (&worker->lock);
-                    thread_cond_signal (&worker->cond);
-                    thread_mutex_unlock (&worker->lock);
+                    worker_wakeup (worker);
                 }
             }
 

Modified: icecast/branches/kh/icecast/src/cfgfile.c
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.c	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/cfgfile.c	2010-08-04 00:59:21 UTC (rev 17362)
@@ -692,11 +692,11 @@
         if (config->access_log.size == 0)
             config->access_log.size = old_trigger_size;
     }
-    if (old_archive > 0)
+    if (old_archive > -1)
     {
-        if (config->error_log.archive == 0)
+        if (config->error_log.archive == -1)
             config->error_log.archive = old_archive;
-        if (config->access_log.archive == 0)
+        if (config->access_log.archive == -1)
             config->access_log.archive = old_archive;
     }
     return 0;

Modified: icecast/branches/kh/icecast/src/cfgfile.h
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.h	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/cfgfile.h	2010-08-04 00:59:21 UTC (rev 17362)
@@ -178,18 +178,18 @@
 
 typedef struct _relay_server
 {
+    struct _relay_server *next, *new_details;
+    struct source_tag *source;
     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;
     time_t start;
-    struct _relay_server *next;
 } relay_server;
 
 

Modified: icecast/branches/kh/icecast/src/client.c
===================================================================
--- icecast/branches/kh/icecast/src/client.c	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/client.c	2010-08-04 00:59:21 UTC (rev 17362)
@@ -22,12 +22,14 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <fcntl.h>
 
 #include "thread/thread.h"
 #include "avl/avl.h"
 #include "httpp/httpp.h"
 #include "timing/timing.h"
 
+#include "client.h"
 #include "cfgfile.h"
 #include "connection.h"
 #include "refbuf.h"
@@ -39,6 +41,7 @@
 #include "logging.h"
 #include "slave.h"
 #include "global.h"
+#include "util.h"
 
 #undef CATMODULE
 #define CATMODULE "client"
@@ -328,36 +331,28 @@
 }
 
 
+/* worker mutex should be already locked */
 static void worker_add_client (worker_t *worker, client_t *client)
 {
-    *worker->last_p = client;
-    worker->last_p = &client->next_on_worker;
+    ++worker->pending_count;
+    client->next_on_worker = NULL;
+    *worker->pending_clients_tail = client;
+    worker->pending_clients_tail = &client->next_on_worker;
     client->worker = worker;
-    ++worker->count;
-    if (worker->wakeup_ms - worker->time_ms > 15)
-        thread_cond_signal (&worker->cond); /* wake thread if required */
 }
 
 
 int client_change_worker (client_t *client, worker_t *dest_worker)
 {
-    worker_t *this_worker = client->worker;
-
     if (dest_worker->running == 0)
         return 0;
-    // make sure this client list is ok
-    *this_worker->current_p = client->next_on_worker;
-    if (client->next_on_worker == NULL)
-        this_worker->last_p = this_worker->current_p;
-    this_worker->count--;
-    thread_mutex_unlock (&this_worker->lock);
     client->next_on_worker = NULL;
 
-    thread_mutex_lock (&dest_worker->lock);
+    thread_spin_lock (&dest_worker->lock);
     worker_add_client (dest_worker, client);
+    thread_spin_unlock (&dest_worker->lock);
+    worker_wakeup (dest_worker);
 
-    thread_mutex_unlock (&dest_worker->lock);
-    thread_mutex_lock (&this_worker->lock);
     return 1;
 }
 
@@ -369,60 +364,139 @@
     thread_rwlock_rlock (&workers_lock);
     /* add client to the handler with the least number of clients */
     handler = find_least_busy_handler();
-    thread_mutex_lock (&handler->lock);
+    thread_spin_lock (&handler->lock);
     thread_rwlock_unlock (&workers_lock);
 
-    client->schedule_ms = handler->time_ms;
     worker_add_client (handler, client);
-    thread_mutex_unlock (&handler->lock);
+    thread_spin_unlock (&handler->lock);
+    worker_wakeup (handler);
 }
 
+#ifdef _WIN32
+#define pipe_create         sock_create_pipe_emulation
+#define pipe_write(A, B, C) send(A, B, C, 0)
+#define pipe_read(A,B,C)    recv(A, B, C, 0)
+#else
+#define pipe_create pipe
+#define pipe_write write
+#define pipe_read read
+#endif
 
+static void worker_move_clients (worker_t *from)
+{
+    client_t *client = from->clients;
+
+    if (workers == NULL || from == NULL || workers->running == 0)
+        return;
+    while (client)
+    {
+        client->worker = workers;
+        client = client->next_on_worker;
+    }
+    thread_spin_lock (&workers->lock);
+    *workers->pending_clients_tail = from->clients;
+    workers->pending_clients_tail = from->last_p;
+    workers->pending_count += from->count;
+    thread_spin_unlock (&workers->lock);
+    from->count = 0;
+    from->clients = NULL;
+    from->last_p = &from->clients;
+}
+
+static void worker_add_pending_clients (worker_t *worker)
+{
+    if (worker && worker->pending_clients)
+    {
+        unsigned count;
+        thread_spin_lock (&worker->lock);
+        *worker->last_p = worker->pending_clients;
+        worker->last_p = worker->pending_clients_tail;
+        worker->count += worker->pending_count;
+        count = worker->pending_count;
+        worker->pending_clients = NULL;
+        worker->pending_clients_tail = &worker->pending_clients;
+        worker->pending_count = 0;
+        thread_spin_unlock (&worker->lock);
+        DEBUG2 ("Added %d pending clients to %p", count, worker);
+    }
+}
+
+
+static void worker_wait (worker_t *worker)
+{
+    uint64_t now = timing_get_time();
+    int ret, duration = (int)(worker->wakeup_ms - now);
+    char ca[30];
+
+    if (duration > 60000) /* make duration between 5 and 60ms */
+        duration = 60000;
+    if (duration < 3)
+        duration = 3;
+
+    ret = util_timed_wait_for_fd (worker->wakeup_fd[0], duration);
+    if (ret > 0) /* may of been several wakeup attempts */
+        pipe_read (worker->wakeup_fd[0], ca, sizeof ca);
+
+    worker_add_pending_clients (worker);
+
+    worker->time_ms = timing_get_time();
+    worker->current_time.tv_sec = worker->time_ms/1000;
+    worker->current_time.tv_nsec = worker->current_time.tv_sec - (worker->time_ms*1000);
+    worker->wakeup_ms = worker->time_ms + 60000;
+}
+
+
 void *worker (void *arg)
 {
     worker_t *handler = arg;
     client_t *client, **prevp;
     long prev_count = -1;
-    struct timespec wakeup_time;
 
     handler->running = 1;
-    thread_mutex_lock (&handler->lock);
-    thread_get_timespec (&handler->current_time);
-    handler->time_ms = THREAD_TIME_MS (&handler->current_time);
-    wakeup_time = handler->current_time;
-
+    handler->wakeup_ms = (int64_t)0;
     prevp = &handler->clients;
     while (1)
     {
-        if (handler->running == 0 && handler->count == 0)
-            break;
+        if (handler->running == 0)
+        {
+            handler->wakeup_ms = handler->time_ms + 50;
+            worker_add_pending_clients (handler);
+            if (handler->count == 0)
+                break;
+            worker_move_clients (handler);
+        }
         if (prev_count != handler->count)
         {
             DEBUG2 ("%p now has %d clients", handler, handler->count);
             prev_count = handler->count;
         }
-        thread_cond_timedwait (&handler->cond, &handler->lock, &wakeup_time);
-        thread_get_timespec (&handler->current_time);
-        handler->time_ms = THREAD_TIME_MS (&handler->current_time);
-        handler->wakeup_ms = handler->time_ms + 60000;
+
+        worker_wait (handler);
         client = handler->clients;
         prevp = &handler->clients;
         while (client)
         {
+            if (client->worker != handler)
+                abort();
             /* process client details but skip those that are not ready yet */
             if (client->flags & CLIENT_ACTIVE)
             {
-                if (client->schedule_ms <= handler->time_ms+15)
+                if (client->schedule_ms <= handler->time_ms+10)
                 {
                     int ret;
+                    client_t *nx = client->next_on_worker;
 
-                    handler->current_p = prevp;
+                    client->schedule_ms = handler->time_ms;
                     ret = client->ops->process (client);
 
                     /* special handler, client has moved away to another worker */
                     if (ret > 0)
                     {
-                        client = *prevp;
+                        handler->count--;
+                        if (nx == NULL) /* moved last client */
+                            handler->last_p = prevp;
+                        *prevp = nx;
+                        client = nx;
                         continue;
                     }
                     if (ret < 0)
@@ -446,12 +520,7 @@
             prevp = &client->next_on_worker;
             client = *prevp;
         }
-        handler->wakeup_ms += 10;  /* allow a small sleep */
-
-        wakeup_time.tv_sec =  (long)(handler->wakeup_ms/1000);
-        wakeup_time.tv_nsec = (long)((handler->wakeup_ms - (wakeup_time.tv_sec*1000))*1000000);
     }
-    thread_mutex_unlock (&handler->lock);
     INFO0 ("shutting down");
     return NULL;
 }
@@ -461,8 +530,13 @@
 {
     worker_t *handler = calloc (1, sizeof(worker_t));
 
-    thread_mutex_create (&handler->lock);
-    thread_cond_create (&handler->cond);
+    if (pipe_create (&handler->wakeup_fd[0]) < 0)
+    {
+        ERROR0 ("pipe failed, fd limit?");
+        abort();
+    }
+    handler->pending_clients_tail = &handler->pending_clients;
+    thread_spin_create (&handler->lock);
     thread_rwlock_wlock (&workers_lock);
     handler->last_p = &handler->clients;
     handler->next = workers;
@@ -475,8 +549,6 @@
 static void worker_stop (void)
 {
     worker_t *handler;
-    client_t *clients = NULL, **last;
-    int count;
 
     if (workers == NULL)
         return;
@@ -486,45 +558,30 @@
     worker_count--;
     thread_rwlock_unlock (&workers_lock);
 
-    thread_mutex_lock (&handler->lock);
     handler->running = 0;
-    thread_cond_signal (&handler->cond);
-    thread_mutex_unlock (&handler->lock);
+    worker_wakeup (handler);
 
-    thread_sleep (10000);
-    thread_mutex_lock (&handler->lock);
-    clients = handler->clients;
-    last = handler->last_p;
-    count = handler->count;
-    thread_cond_signal (&handler->cond);
-    thread_mutex_unlock (&handler->lock);
-    if (clients)
-    {
-        if (worker_count == 0)
-            WARN0 ("clients left unprocessed");
-        else
-        {
-            thread_mutex_lock (&workers->lock);
-            *workers->last_p = clients;
-            workers->last_p = last;
-            workers->count += count;
-            thread_mutex_unlock (&workers->lock);
-        }
-    }
     thread_join (handler->thread);
-    thread_mutex_destroy (&handler->lock);
-    thread_cond_destroy (&handler->cond);
+    thread_spin_destroy (&handler->lock);
+
+    sock_close (handler->wakeup_fd[1]);
+    sock_close (handler->wakeup_fd[0]);
     free (handler);
 }
 
 void workers_adjust (int new_count)
 {
+    INFO1 ("requested worker count %d", new_count);
     while (worker_count != new_count)
     {
         if (worker_count < new_count)
             worker_start ();
-        else
+        else if (worker_count > new_count)
             worker_stop ();
     }
 }
 
+void worker_wakeup (worker_t *worker)
+{
+    pipe_write (worker->wakeup_fd[1], "W", 1);
+}

Modified: icecast/branches/kh/icecast/src/client.h
===================================================================
--- icecast/branches/kh/icecast/src/client.h	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/client.h	2010-08-04 00:59:21 UTC (rev 17362)
@@ -31,11 +31,14 @@
 struct _worker_t
 {
     int running;
-    int count;
-    mutex_t lock;
-    cond_t cond;
-    client_t *clients;
-    client_t **current_p, **last_p;
+    int count, pending_count;
+    spin_t lock;
+    int wakeup_fd[2];
+
+    client_t *pending_clients;
+    client_t **pending_clients_tail,
+             *clients;
+    client_t **last_p;
     thread_type *thread;
     struct timespec current_time;
     uint64_t time_ms;
@@ -134,6 +137,7 @@
 void client_add_worker (client_t *client);
 worker_t *find_least_busy_handler (void);
 void workers_adjust (int new_count);
+void worker_wakeup (worker_t *worker);
 
 
 /* client flags bitmask */

Modified: icecast/branches/kh/icecast/src/connection.c
===================================================================
--- icecast/branches/kh/icecast/src/connection.c	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/connection.c	2010-08-04 00:59:21 UTC (rev 17362)
@@ -878,7 +878,6 @@
                     ERROR0("Bad HTTP protocol detected");
                     return -1;
                 }
-                client->schedule_ms = client->worker->time_ms + 20;
                 auth_check_http (client);
                 switch (client->parser->req_type)
                 {
@@ -897,8 +896,9 @@
                     default:
                         WARN0("unhandled request type from client");
                         client_send_400 (client, "unknown request");
+                        return 0;
                 }
-                return 0;
+                return client->ops->process(client);
             }
             /* invalid http request */
             return -1;

Modified: icecast/branches/kh/icecast/src/flv.c
===================================================================
--- icecast/branches/kh/icecast/src/flv.c	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/flv.c	2010-08-04 00:59:21 UTC (rev 17362)
@@ -57,7 +57,7 @@
 
 static void flv_hdr (struct flv *flv, unsigned int len)
 {
-    unsigned long v = flv->prev_tagsize;
+    long  v = flv->prev_tagsize;
 
     v = flv->prev_tagsize;
     flv->tag [3] = v & 0xFF;
@@ -66,21 +66,21 @@
     v >>= 8;
     flv->tag [1] = v & 0xFF; // assume less than 2^24 
 
-    v = len;
-    flv->tag [7] = v & 0xFF;
+    v = (long)len;
+    flv->tag [7] = (unsigned char)(v & 0xFF);
     v >>= 8;
-    flv->tag [6] = v & 0xFF;
+    flv->tag [6] = (unsigned char)(v & 0xFF);
     v >>= 8;
-    flv->tag [5] = v & 0xFF;
+    flv->tag [5] = (unsigned char)(v & 0xFF);
 
-    v = flv->prev_ms;
-    flv->tag [10] = v & 0xFF;
+    v = (long)flv->prev_ms;
+    flv->tag [10] = (unsigned char)(v & 0xFF);
     v >>= 8;
-    flv->tag [9] = v & 0xFF;
+    flv->tag [9] = (unsigned char)(v & 0xFF);
     v >>= 8;
-    flv->tag [8] = v & 0xFF;
+    flv->tag [8] = (unsigned char)(v & 0xFF);
     v >>= 8;
-    flv->tag [11] = v & 0xFF;
+    flv->tag [11] = (unsigned char)(v & 0xFF);
 
 }
 
@@ -109,7 +109,7 @@
     }
     memcpy (mp->raw->data + mp->raw_offset, &flv->tag[0], 16);
     flv->samples += mp->sample_count;
-    flv->prev_ms = (flv->samples / (mp->samplerate/1000.0)) + 0.5;
+    flv->prev_ms = (int64_t)(flv->samples / (mp->samplerate/1000.0));
     // The extra byte is for the flv audio id, usually 0x2F 
     flv->prev_tagsize = (len + FLVHEADER + 1);
     mp->raw_offset += 16;
@@ -129,7 +129,7 @@
     // a single frame (headerless) follows this
     memcpy (mp->raw->data + mp->raw_offset, &flv->tag[0], 17);
     flv->samples += mp->sample_count;
-    flv->prev_ms = (flv->samples / (mp->samplerate/1000.0)) + 0.5;
+    flv->prev_ms = (int64_t)(flv->samples / (mp->samplerate/1000.0));
     // frame length + FLVHEADER + AVHEADER
     flv->prev_tagsize = (len + 11 + 2);
     mp->raw_offset += 17;
@@ -179,17 +179,18 @@
 
 static int send_flv_buffer (client_t *client, struct flv *flv)
 {
-    int ret;
+    int ret = 0;
     char *buf = flv->mpeg_sync.raw->data + flv->block_pos;
     unsigned int len  = flv->mpeg_sync.raw_offset - flv->block_pos;
 
-    if (len <= 0)
-        return 0;
-    ret = client_send_bytes (client, buf, len);
-    if (ret < (int)len)
-        client->schedule_ms += 300;
-    if (ret > 0)
-        flv->block_pos += ret;
+    if (len > 0)
+    {
+        ret = client_send_bytes (client, buf, len);
+        if (ret < (int)len)
+            client->schedule_ms += (ret ? 20 : 150);
+        if (ret > 0)
+            flv->block_pos += ret;
+    }
     if (flv->block_pos == flv->mpeg_sync.raw_offset)
         flv->block_pos = flv->mpeg_sync.raw_offset = 0;
     return ret;
@@ -201,11 +202,8 @@
     refbuf_t *ref = client->refbuf, *scmeta = ref->associated;
     mp3_client_data *client_mp3 = client->format_data;
     struct flv *flv = client_mp3->specific;
-    int unprocessed, ret = -1;
+    int ret;
 
-    if (flv->block_pos)
-        return send_flv_buffer (client, flv);
-
     /* check for metadata updates and insert if needed */
     if (flv->seen_metadata != scmeta)
     {
@@ -247,15 +245,20 @@
         flv->seen_metadata = ref->associated;
     }
 
-    unprocessed = mpeg_complete_frames (&flv->mpeg_sync, ref, client->pos);
-    client->pos = ref->len;
-    client->queue_pos += ref->len;
-    if (unprocessed >= 0)
+    if (flv->mpeg_sync.raw_offset == 0)
     {
-        ret = send_flv_buffer (client, flv);
+        int unprocessed = mpeg_complete_frames (&flv->mpeg_sync, ref, client->pos);
+        if (unprocessed < 0)
+            return -1;
         if (unprocessed > 0)
             ref->len += unprocessed;   /* output was truncated, so revert changes */
     }
+    ret = send_flv_buffer (client, flv);
+    if (flv->mpeg_sync.raw_offset == 0)
+    {
+        client->pos = ref->len;
+        client->queue_pos += client->refbuf->len;
+    }
     return ret;
 }
 
@@ -273,11 +276,25 @@
     char *ptr;
     refbuf_t *buffer = refbuf_new (sizeof (struct flvmeta) + len + 30);
     struct flvmeta *flvm = (struct flvmeta *)buffer->data;
+
     memset (flvm, 0, sizeof (struct flvmeta));
     ptr = buffer->data + sizeof (struct flvmeta);
     memcpy (ptr, "\002\000\012onMetaData", 13);
     memcpy (ptr+13, "\010\000\000\000\000", 5);
-    flvm->meta_pos = sizeof (struct flvmeta) + 18;
+    flvm->meta_pos = 18;
+    flvm->arraylen = 0;
+
+#if 0
+    flvm->arraylen = 1;
+    memcpy (ptr+18, "\000\010duration\000", 11);
+    flvm->meta_pos += 2+8+1;
+    {
+        // 1 billion as a double, endian matters. hex 00 41 cd cd  65 00 00 00 00
+        memcpy (ptr+flvm->meta_pos, "\101\315\315\145\000\000\000\000", 8);
+        flvm->meta_pos += 8;
+    }
+#endif
+    flvm->meta_pos += sizeof (struct flvmeta);
     return buffer;
 }
 
@@ -324,6 +341,7 @@
     char *ptr = client->refbuf->data;
 
     mpeg_setup (&flv->mpeg_sync, plugin->mount);
+    mpeg_check_numframes (&flv->mpeg_sync, 1); 
     client_mp3->specific = flv;
 
     bytes = snprintf (ptr, 200, "HTTP/1.0 200 OK\r\n"

Modified: icecast/branches/kh/icecast/src/format_mp3.c
===================================================================
--- icecast/branches/kh/icecast/src/format_mp3.c	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/format_mp3.c	2010-08-04 00:59:21 UTC (rev 17362)
@@ -205,7 +205,7 @@
     source_mp3->interval = -1;
     free (format->charset);
     format->charset = NULL;
-    source_mp3->queue_block_size = 2900;
+    source_mp3->queue_block_size = 1400;
 
     if (mount)
     {
@@ -259,7 +259,7 @@
     {
         char *end = strstr (source_mp3->inline_url, "';");
         if (end)
-            len += end - source_mp3->inline_url+2;
+            len += end - source_mp3->inline_url + strlen (streamurl) + 2;
     }
     else if (source_mp3->url)
         len += strlen (source_mp3->url) + strlen (streamurl) + 2;
@@ -300,10 +300,13 @@
             if (source_mp3->inline_url)
             {
                 char *end = strstr (source_mp3->inline_url, "';");
-                int urllen = size;
-                if (end) urllen = end - source_mp3->inline_url + 2;
-                if (size-r > urllen)
-                    snprintf (p->data+r, size-r, "StreamUrl='%s';", source_mp3->inline_url+11);
+                if (end)
+                {
+                    int urllen = end - source_mp3->inline_url;
+                    int len = urllen + strlen("StreamUrl='") + 3;
+                    if (size-r > len);
+                        snprintf (p->data+r, len, "StreamUrl='%.*s';", urllen, source_mp3->inline_url);
+                }
             }
             else if (source_mp3->url)
             {
@@ -384,14 +387,14 @@
             {
                 client_mp3->metadata_offset += (ret - remaining);
                 client->flags |= CLIENT_IN_METADATA;
-                client->schedule_ms += 300;
+                client->schedule_ms += 200;
             }
             client_mp3->since_meta_block = 0;
             client->pos += remaining;
             client->queue_pos += remaining;
             return ret;
         }
-        client->schedule_ms += 300;
+        client->schedule_ms += 200;
         if (ret > 0)
         {
             client_mp3->since_meta_block += ret;
@@ -411,7 +414,7 @@
     }
     if (ret > 0)
         client_mp3->metadata_offset += ret;
-    client->schedule_ms += 300;
+    client->schedule_ms += 200;
     client->flags |= CLIENT_IN_METADATA;
 
     return ret > 0 ? ret : 0;
@@ -427,7 +430,7 @@
     mp3_client_data *client_mp3 = client->format_data;
     refbuf_t *refbuf = client->refbuf;
     char *buf = refbuf->data + client->pos;
-    size_t len = refbuf->len - client->pos;
+    unsigned int len = refbuf->len - client->pos;
 
     do
     {
@@ -477,7 +480,7 @@
     } while (0);
 
     if (ret < 0)
-        client->schedule_ms += 250;
+        client->schedule_ms += (written ? 25 : 50);
     if (ret > 0)
         written += ret;
     return written == 0 ? -1 : written;
@@ -724,6 +727,8 @@
                 yp_touch (source->mount);
                 free (title);
                 source_mp3->inline_url = strstr (meta->data+1, "StreamUrl='");
+                if (source_mp3->inline_url)
+                    source_mp3->inline_url += 11;
                 flv_meta_append (flvmeta, NULL, NULL);
                 meta->associated = flvmeta;
                 refbuf_release (source_mp3->metadata);
@@ -787,6 +792,7 @@
     {
         client_mp3->specific = calloc (1, sizeof(mpeg_sync));
         mpeg_setup (client_mp3->specific, plugin->mount);
+        mpeg_check_numframes (client_mp3->specific, 1);
     }
 
     if (format_general_headers (plugin, client) < 0)

Modified: icecast/branches/kh/icecast/src/format_ogg.c
===================================================================
--- icecast/branches/kh/icecast/src/format_ogg.c	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/format_ogg.c	2010-08-04 00:59:21 UTC (rev 17362)
@@ -533,7 +533,7 @@
         }
         if (ret < (int)len)
         {
-            client->schedule_ms += 250;
+            client->schedule_ms += 50;
             return written ? written : -1;
         }
         if (client_data->pos == refbuf->len)
@@ -584,7 +584,7 @@
         }
 
         if (ret < (int)len)
-            client->schedule_ms += 250;
+            client->schedule_ms += 50;
     } while (0);
 
     return written ? written : -1;

Modified: icecast/branches/kh/icecast/src/fserve.c
===================================================================
--- icecast/branches/kh/icecast/src/fserve.c	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/fserve.c	2010-08-04 00:59:21 UTC (rev 17362)
@@ -56,6 +56,7 @@
 #include "compat.h"
 
 #include "fserve.h"
+#include "format_mp3.h"
 
 #undef CATMODULE
 #define CATMODULE "fserve"
@@ -818,6 +819,7 @@
     time_t now = client->worker->current_time.tv_sec;
     unsigned long secs = now - client->timer_start; 
     unsigned int  rate = secs ? ((client->counter+1400)/secs) : 0;
+    unsigned int limit = fh->finfo.limit;
 
     if (fserve_running == 0 || client->connection.error)
         return -1;
@@ -829,7 +831,9 @@
         return 0;
     }
     thread_mutex_lock (&fh->lock);
-    if (rate >= fh->finfo.limit)
+    if (client->flags & CLIENT_WANTS_FLV) /* increase limit for flv clients as wrapping takes more space */
+        limit = (unsigned long)(limit * 1.02);
+    if (rate > limit)
     {
         client->schedule_ms = client->worker->time_ms + (1000*(rate - fh->finfo.limit))/fh->finfo.limit;
         rate_add (fh->format->out_bitrate, 0, client->worker->time_ms);
@@ -916,10 +920,8 @@
         client->schedule_ms = client->worker->time_ms;
     else
     {
-        thread_mutex_lock (&client->worker->lock);
         client->flags |= CLIENT_ACTIVE;
-        thread_cond_signal (&client->worker->cond);
-        thread_mutex_unlock (&client->worker->lock);
+        worker_wakeup (client->worker);
     }
     return 0;
 }

Modified: icecast/branches/kh/icecast/src/mpeg.c
===================================================================
--- icecast/branches/kh/icecast/src/mpeg.c	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/mpeg.c	2010-08-04 00:59:21 UTC (rev 17362)
@@ -124,11 +124,11 @@
         bitrate *= 1000;
         if (mp->layer == LAYER_1)
         {
-            frame_len = (12 * bitrate / mp->samplerate + padding) * 4; // ??
+            frame_len = (int)(12 * bitrate / mp->samplerate + padding) * 4; // ??
         }
         else
         {
-            frame_len = samples / 8 * bitrate / mp->samplerate + padding;
+            frame_len = (int)(samples / 8 * bitrate / mp->samplerate + padding);
         }
     }
     return frame_len;
@@ -163,7 +163,7 @@
             v = (p[2] << 8) + p[3],
             channels_idx = (v & 0x1C0) >> 6;
         int id =  p[1] & 0x8;
-        int checking = 4;
+        int checking = mp->check_numframes;
         unsigned char *fh = p;
 
         while (checking)
@@ -208,7 +208,7 @@
         mp->ver = (p[1] & 0x18) >> 3;
         if (mp->layer && version [mp->ver] && layer[mp->layer]) 
         {
-            int checking = 4;
+            int checking = mp->check_numframes;
             unsigned char *fh = p;
             int samplerates [4][4] = {
                 { 11025, 0, 22050, 44100},
@@ -381,9 +381,16 @@
 void mpeg_setup (mpeg_sync *mpsync, const char *mount)
 {
     memset (mpsync, 0, sizeof (mpeg_sync));
+    mpsync->check_numframes = 4;
     mpsync->mount = mount;
 }
 
+void mpeg_check_numframes (mpeg_sync *mpsync, unsigned count)
+{
+    if (count && count < 100)
+        mpsync->check_numframes = count;
+}
+
 void mpeg_cleanup (mpeg_sync *mpsync)
 {
     if (mpsync)

Modified: icecast/branches/kh/icecast/src/mpeg.h
===================================================================
--- icecast/branches/kh/icecast/src/mpeg.h	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/mpeg.h	2010-08-04 00:59:21 UTC (rev 17362)
@@ -32,11 +32,13 @@
     int layer;
     int samplerate;
     int channels;
+    int check_numframes;
     const char *mount;
 } mpeg_sync;
 
 void mpeg_setup (mpeg_sync *mpsync, const char *mount);
 void mpeg_cleanup (mpeg_sync *mpsync);
+void mpeg_check_numframes (mpeg_sync *mpsync, unsigned count);
 
 int  mpeg_complete_frames (mpeg_sync *mp, refbuf_t *new_block, unsigned offset);
 void mpeg_data_insert (mpeg_sync *mp, refbuf_t *inserted);

Modified: icecast/branches/kh/icecast/src/slave.c
===================================================================
--- icecast/branches/kh/icecast/src/slave.c	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/slave.c	2010-08-04 00:59:21 UTC (rev 17362)
@@ -223,13 +223,13 @@
 #endif
     _slave_thread ();
     slave_running = 0;
+    workers_adjust(0);
 }
 
 
 void slave_shutdown(void)
 {
     yp_stop();
-    workers_adjust (0);
     thread_rwlock_destroy (&slaves_lock);
     thread_rwlock_destroy (&workers_lock);
     thread_spin_destroy (&relay_start_lock);
@@ -383,24 +383,16 @@
         else
             INFO3 ("connecting to %s:%d for %s", server, port, relay->localmount);
 
-        thread_mutex_unlock (&client->worker->lock);
         streamsock = sock_connect_wto_bind (server, port, bind, timeout);
         free (bind);
         if (connection_init (con, streamsock, server) < 0)
         {
             WARN2 ("Failed to connect to %s:%d", server, port);
-            thread_mutex_lock (&client->worker->lock);
             break;
         }
 
         parser = get_relay_response (con, mount, server, ask_for_metadata, auth_header);
 
-        thread_mutex_lock (&client->worker->lock);
-        if (relay != client->shared_data)   /* unusual but possible */
-        {
-            INFO0 ("detected relay change, retrying");
-            break;
-        }
         if (parser == NULL)
         {
             ERROR4 ("Problem trying to start relay on %s (%s:%d%s)", relay->localmount,
@@ -465,6 +457,7 @@
     free (auth_header);
     if (parser)
         httpp_destroy (parser);
+    connection_close (con);
     return -1;
 }
 
@@ -485,11 +478,6 @@
         ret = open_relay_connection (client, relay, master);
         thread_mutex_lock (&src->lock);
 
-        if (relay != client->shared_data)
-        {
-            relay = client->shared_data; // relay data may of changed
-            master = relay->masters;
-        }
         if (ret < 0)
             continue;
 
@@ -510,6 +498,7 @@
     relay_server *relay;
     source_t *src;
     int failed = 1, sources;
+    time_t start = time (NULL);
 
     global_lock();
     sources = ++global.sources;
@@ -519,7 +508,6 @@
     {
         ice_config_t *config = config_get_config();
 
-        thread_mutex_lock (&client->worker->lock);
         relay = client->shared_data;
         src = relay->source;
 
@@ -541,13 +529,12 @@
         failed = 0;
     } while (0);
 
-    relay = client->shared_data; // relay may of changed during open_relay
     client->ops = &relay_client_ops;
     client->schedule_ms = timing_get_time();
 
     if (failed)
     {
-        /* failed to start, better clean up and reset */
+        /* failed to start any connection, better clean up and reset */
         if (relay->on_demand)
             src->flags &= ~SOURCE_ON_DEMAND;
         else
@@ -556,11 +543,23 @@
         INFO2 ("listener count remaining on %s is %d", src->mount, src->listeners);
         src->flags &= ~SOURCE_PAUSE_LISTENERS;
         thread_mutex_unlock (&src->lock);
-        relay->start = client->schedule_ms/1000;
+        relay->start = (time_t)(client->schedule_ms/1000);
         if (relay->on_demand)
-            relay->start += 5;
+            relay->start += 3;
         else
-            relay->start += relay->interval;
+        {
+            if (relay->running && start - relay->start < 300)
+            {
+                INFO1 ("relay %s terminated too quickly, will restart in 30s", relay->localmount);
+                relay->start += 30;
+            }
+            else
+                relay->start += relay->interval;
+        }
+        global_lock();
+        global.sources--;
+        stats_event_args (NULL, "sources", "%d", global.sources);
+        global_unlock();
     }
 
     thread_spin_lock (&relay_start_lock);
@@ -568,8 +567,7 @@
     thread_spin_unlock (&relay_start_lock);
 
     client->flags |= CLIENT_ACTIVE;
-    thread_cond_signal (&client->worker->cond);
-    thread_mutex_unlock (&client->worker->lock);
+    worker_wakeup (client->worker);
     return NULL;
 }
 
@@ -612,9 +610,11 @@
         client->ops = &relay_startup_ops;
         if (relay->on_demand)
         {
-            ice_config_t *config = config_get_config();
-            mount_proxy *mountinfo = config_find_mount (config, source->mount);
+            ice_config_t *config;
+            mount_proxy *mountinfo;
             thread_mutex_lock (&source->lock);
+            config = config_get_config();
+            mountinfo = config_find_mount (config, source->mount);
             source->flags |= SOURCE_ON_DEMAND;
             source_update_settings (config, source, mountinfo);
             thread_mutex_unlock (&source->lock);
@@ -685,19 +685,19 @@
 
                 if (global.running == ICE_RUNNING && relay_has_changed (relay, existing_relay))
                 {
-                    client_t *client = existing_relay->source->client;
+                    source_t *source = existing_relay->source;
                     new = relay_copy (relay);
-                    thread_mutex_lock (&client->worker->lock);
-                    existing_relay->cleanup = 0;
-                    client->shared_data = new;
-                    new->source = existing_relay->source;
-                    existing_relay->source = NULL;
-                    new->running = 1;
-                    thread_mutex_unlock (&client->worker->lock);
                     INFO1 ("relay details changed on \"%s\", restarting", new->localmount);
+                    existing_relay->new_details = new;
+                    if (source && source->client)
+                    {
+                        /* wakeup client to change relay details */
+                        client_t *client = source->client;
+                        client->schedule_ms = 0;
+                        worker_wakeup (client->worker);
+                    }
                 }
-                else
-                    *existing_p = existing_relay->next;
+                *existing_p = existing_relay->next; /* leave client to free structure */
                 new->next = new_list;
                 new_list = new;
                 break;
@@ -1247,10 +1247,26 @@
             redirect->server, redirect->port);
 }
 
+static relay_server *get_relay_details (client_t *client)
+{
+    relay_server *relay = client->shared_data;
+    if (relay && relay->new_details)
+    {
+        relay_server *old_details = relay;
+        INFO1 ("Detected change in relay details for %s", relay->localmount);
+        client->shared_data = relay->new_details;
+        relay->source = old_details->source;
+        old_details->source = NULL;
+        relay_free (relay);
+        relay = client->shared_data;
+    }
+    return relay;
+}
 
+
 static int relay_read (client_t *client)
 {
-    relay_server *relay = client->shared_data;
+    relay_server *relay = get_relay_details (client);
     source_t *source = relay->source;
     int ret = -1;
 
@@ -1275,11 +1291,6 @@
             stats_event_args (NULL, "sources", "%d", global.sources);
             global_unlock();
             global_reduce_bitrate_sampling (global.out_bitrate);
-            if (client->worker->current_time.tv_sec - client->connection.con_time < 300)
-            {
-                INFO1 ("relay %s terminated quickly, will restart in 60s", relay->localmount);
-                relay->start = client->worker->current_time.tv_sec + 60;
-            }
             connection_close (&client->connection);
         }
         /* don't pause listeners if relay shutting down */
@@ -1333,13 +1344,14 @@
 
 static int relay_startup (client_t *client)
 {
-    relay_server *relay = client->shared_data;
+    relay_server *relay = get_relay_details (client);
 
     if (relay->cleanup)
     {
         /* listeners may be still on, do a recheck */
         relay->running = 0;
         client->ops = &relay_client_ops;
+        client->schedule_ms += 25;
         return 0;
     }
     if (global.running != ICE_RUNNING)
@@ -1379,7 +1391,7 @@
         }
         if (start_relay == 0)
         {
-            client->schedule_ms = client->worker->time_ms + 1000;
+            client->schedule_ms += 500;
             return 0;
         }
         INFO1 ("Detected listeners on relay %s", relay->localmount);
@@ -1390,7 +1402,7 @@
     if (relays_connecting > 3)
     {
         thread_spin_unlock (&relay_start_lock);
-        client->schedule_ms = client->worker->time_ms + 1000;
+        client->schedule_ms += 500;
         return 0;
     }
     relays_connecting++;

Modified: icecast/branches/kh/icecast/src/source.c
===================================================================
--- icecast/branches/kh/icecast/src/source.c	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/source.c	2010-08-04 00:59:21 UTC (rev 17362)
@@ -427,8 +427,7 @@
 {
     client_t *client = source->client;
     refbuf_t *refbuf = NULL;
-    int skip = 1;
-    int loop = 3;
+    int skip = 1, loop = 3;
     time_t current = client->worker->current_time.tv_sec;
     int fds = 0;
 
@@ -471,7 +470,7 @@
             {
                 rate_add (source->format->in_bitrate, 0, current);
                 source->skip_duration += 300;
-                client->schedule_ms = client->worker->time_ms + 150;
+                client->schedule_ms += 150;
                 thread_mutex_unlock (&source->lock);
                 return 0;
             }
@@ -497,16 +496,15 @@
                 skip = 0;
                 break;
             }
-            source->skip_duration = (long)(source->skip_duration * 1.8);
+            source->skip_duration = (int)(source->skip_duration * 1.6);
             if (source->skip_duration > 700)
                 source->skip_duration = 700;
             break;
         }
         source->skip_duration = (long)(source->skip_duration * 0.9);
-        if (source->skip_duration < 5)
+        if (source->skip_duration < 5) /* not too low or else it will not be able to increase */
             source->skip_duration = 5;
 
-        skip = 0;
         source->last_read = current;
         do
         {
@@ -555,20 +553,20 @@
                 /* save stream to file */
                 if (source->dumpfile && source->format->write_buf_to_file)
                     source->format->write_buf_to_file (source, refbuf);
-                client->schedule_ms = client->worker->time_ms + 5;
+                skip = 0;
             }
             else
             {
-                skip = 1;
                 if (client->connection.error)
                 {
                     INFO1 ("End of Stream %s", source->mount);
                     source->flags &= ~SOURCE_RUNNING;
+                    skip = 0;
                 }
                 break;
             }
             loop--;
-        } while (0);
+        } while (loop);
 
         /* lets see if we have too much data in the queue */
         while (source->queue_size > source->queue_size_limit ||
@@ -585,7 +583,9 @@
     } while (0);
 
     if (skip)
-        client->schedule_ms = client->worker->time_ms + source->skip_duration;
+        client->schedule_ms += (source->skip_duration | 0xF);
+    else
+        client->schedule_ms += 15;
     thread_mutex_unlock (&source->lock);
     return 0;
 }
@@ -614,7 +614,7 @@
         if (source->termination_count && source->termination_count <= source->listeners)
         {
             DEBUG3 ("%s waiting (%lu, %lu)", source->mount, source->termination_count, source->listeners);
-            client->schedule_ms = client->worker->time_ms + 200;
+            client->schedule_ms = client->worker->time_ms + 100;
         }
         else
         {
@@ -637,7 +637,7 @@
 
     if (client->refbuf == NULL && locate_start_on_queue (source, client) < 0)
     {
-        client->schedule_ms += 200;
+        client->schedule_ms += 150;
         return -1;
     }
     refbuf = client->refbuf;
@@ -647,7 +647,7 @@
     {
         if (refbuf->next == NULL)
         {
-            client->schedule_ms = source->client->schedule_ms + 20;
+            client->schedule_ms = source->client->schedule_ms + 5;
             return -1;
         }
         client_set_queue (client, refbuf->next);
@@ -670,8 +670,8 @@
     refbuf = source->stream_data_tail;
     if (client->intro_offset == -1 && (refbuf->flags & SOURCE_BLOCK_SYNC))
     {
-        pos = refbuf->len;
-        lag = 0;
+        pos = 0;
+        lag = refbuf->len;
     }
     else
     {
@@ -719,16 +719,14 @@
     }
     if (format_file_read (client, source->intro_file) < 0)
     {
-        client->schedule_ms = client->worker->time_ms + 1000;
         if (source->stream_data_tail)
         {
             /* better find the right place in queue for this client */
             client_set_queue (client, NULL);
             client->check_buffer = source_queue_advance;
-            if (client->connection.sent_bytes == 0) // no intro
-                client->schedule_ms = client->worker->time_ms;
-            return 0;
+            return source_queue_advance (client);
         }
+        client->schedule_ms += 100;
         client->intro_offset = 0;  /* replay intro file */
         return -1;
     }
@@ -740,14 +738,18 @@
 {
     refbuf_t *refbuf = client->refbuf;
     source_t *source = client->shared_data;
+    int ret;
 
     if (refbuf == NULL)
     {
         client->check_buffer = http_source_intro;
-        return -1;
+        return http_source_intro (client);
     }
     if (source->queue_size == 0)
+    {
+        client->schedule_ms += 500;
         return -1;  /* postpone processing until data on queue */
+    }
 
     if (client->respcode == 0)
     {
@@ -755,8 +757,8 @@
 
         if (source_running (source) == 0)
         {
-            client->schedule_ms = client->worker->time_ms + 200;
-            return 0;
+            client->schedule_ms += 200;
+            return -1;
         }
         if (source->format->create_client_data)
             build_headers = source->format->create_client_data;
@@ -769,6 +771,7 @@
         }
         stats_event_inc (source->mount, "listener_connections");
     }
+    ret = format_generic_write_to_client (client);
     if (client->pos == refbuf->len)
     {
         client->check_buffer = http_source_intro;
@@ -783,9 +786,10 @@
         else
             client->pos = refbuf->len = 4096;
         client->connection.sent_bytes = 0;
-        return 0;
+        return ret;
     }
-    return format_generic_write_to_client (client);
+    client->schedule_ms += 200;
+    return ret;
 }
 
 
@@ -847,7 +851,7 @@
 static int send_listener (source_t *source, client_t *client)
 {
     int bytes;
-    int loop = 6;   /* max number of iterations in one go */
+    int loop = 10;   /* max number of iterations in one go */
     long total_written = 0;
     int ret = 0;
 
@@ -863,10 +867,7 @@
         move_failed = move_listener (client, &source->fallback);
         thread_mutex_lock (&source->lock);
         if (move_failed)
-        {
             source_setup_listener (source, client);
-            client->schedule_ms = client->worker->time_ms + 50;
-        }
         source->termination_count--;
         return 0;
     }
@@ -880,7 +881,7 @@
                 client_set_queue (client, NULL);
             client->ops = &listener_pause_ops;
             client->flags |= CLIENT_HAS_MOVED;
-            client->schedule_ms = client->worker->time_ms + 100;
+            client->schedule_ms = client->worker->time_ms + 60;
             return 0;
         }
         return -1;
@@ -894,7 +895,8 @@
     }
     if (source_running (source) == 0)
     {
-        client->schedule_ms = client->worker->time_ms + 200;
+        DEBUG0 ("source not running, listener will wait 200ms");
+        client->schedule_ms += 200;
         return 0;
     }
 
@@ -907,7 +909,6 @@
             return 1;
 
     /* progessive slowdown if nearing max bandwidth.  */
-    client->schedule_ms = client->worker->time_ms;
     if (global.max_rate)
     {
         if (throttle_sends > 2) /* exceeded limit, skip 30ms */
@@ -939,20 +940,14 @@
         /* lets not send too much to one client in one go, but don't
            sleep for too long if more data can be sent */
         if (total_written > source->listener_send_trigger)
-        {
-            client->schedule_ms = client->worker->time_ms;
             break;
-        }
         bytes = client->check_buffer (client);
         if (bytes < 0)
             break;  /* can't write any more */
 
-        client->schedule_ms += 40;
         total_written += bytes;
         loop--;
     }
-    if (loop == 0)
-        client->schedule_ms -= 190;
     rate_add (source->format->out_bitrate, total_written, client->worker->time_ms);
     global_add_bitrates (global.out_bitrate, total_written, client->worker->time_ms);
     source->bytes_sent_since_update += total_written;
@@ -1833,7 +1828,7 @@
     return 0;
 }
 
-/* call with the source lock heldm, but expect the lock released on exit
+/* call with the source lock held, but expect the lock released on exit
  * as the listener may of changed threads and therefore lock needed to be
  * released
  */

Modified: icecast/branches/kh/icecast/src/util.c
===================================================================
--- icecast/branches/kh/icecast/src/util.c	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/util.c	2010-08-04 00:59:21 UTC (rev 17362)
@@ -343,7 +343,6 @@
                 ERROR0("Fatal internal logic error in util_url_unescape()");
                 free(decoded);
                 return NULL;
-                break;
             default:
                 *dst++ = src[i];
                 break;
@@ -375,6 +374,12 @@
         return NULL;
     }
 
+    while (1)
+    {
+        char *s = strstr (path, "//");
+        if (s == NULL) break;
+        memmove (path+1, path+2, strlen (path+2)+1);
+    }
     /* We now have a full URI-decoded path. Check it for allowability */
     if(verify_path(path))
         return path;

Modified: icecast/branches/kh/icecast/src/yp.c
===================================================================
--- icecast/branches/kh/icecast/src/yp.c	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/src/yp.c	2010-08-04 00:59:21 UTC (rev 17362)
@@ -82,6 +82,7 @@
 
 static rwlock_t yp_lock;
 static mutex_t yp_pending_lock;
+int yp_initialised;
 
 static volatile struct yp_server *active_yps = NULL, *pending_yps = NULL;
 static volatile int yp_update = 0;
@@ -243,7 +244,7 @@
     ypclient.counter = 0;
     ypclient.schedule_ms = 0;
     ypclient.connection.error = 0;
-    ypclient.flags = CLIENT_ACTIVE;
+    ypclient.flags = CLIENT_ACTIVE|CLIENT_SKIP_ACCESSLOG;
     client_add_worker (&ypclient);
 }
 
@@ -333,6 +334,7 @@
     thread_rwlock_create (&yp_lock);
     thread_mutex_create (&yp_pending_lock);
     yp_recheck_config (config);
+    yp_initialised = 1;
 }
 
 
@@ -803,11 +805,8 @@
     yp_thread = NULL;
     /* DEBUG0("YP thread shutdown"); */
 
-    thread_mutex_lock (&ypclient.worker->lock);
     ypclient.flags |= CLIENT_ACTIVE;
-    DEBUG1 ("wakeup again in %lu secs", ypclient.counter - time(NULL));
-    thread_cond_signal (&ypclient.worker->cond);
-    thread_mutex_unlock (&ypclient.worker->lock);
+    worker_wakeup (ypclient.worker);
 
     return NULL;
 }
@@ -1029,6 +1028,8 @@
 void yp_shutdown (void)
 {
     DEBUG0 ("releasing directory details");
+    if (yp_initialised == 0)
+        return;
     thread_rwlock_destroy (&yp_lock);
     thread_mutex_destroy (&yp_pending_lock);
 
@@ -1042,6 +1043,7 @@
     free ((char*)server_version);
     server_version = NULL;
     active_yps = NULL;
+    yp_initialised = 0;
     INFO0 ("YP cleanup complete");
 }
 
@@ -1051,11 +1053,9 @@
     worker_t *w = ypclient.worker;
     if (w)
     {
-        thread_mutex_lock (&w->lock);
         ypclient.connection.error = 1;
         ypclient.schedule_ms = 0;
-        thread_cond_signal (&w->cond);
-        thread_mutex_unlock (&w->lock);
+        worker_wakeup(w);
         DEBUG0 ("YP client is now stopped");
     }
 }

Modified: icecast/branches/kh/icecast/win32/icecast.dsp
===================================================================
--- icecast/branches/kh/icecast/win32/icecast.dsp	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/win32/icecast.dsp	2010-08-04 00:59:21 UTC (rev 17362)
@@ -211,7 +211,7 @@
 # End Source File
 # Begin Source File
 
-SOURCE=\src\mpeg.c
+SOURCE=..\src\mpeg.c
 # End Source File
 # Begin Source File
 
@@ -375,7 +375,7 @@
 # End Source File
 # Begin Source File
 
-SOURCE=\src\mpeg.h
+SOURCE=..\src\mpeg.h
 # End Source File
 # Begin Source File
 

Modified: icecast/branches/kh/icecast/win32/icecast2.iss
===================================================================
--- icecast/branches/kh/icecast/win32/icecast2.iss	2010-08-03 23:23:38 UTC (rev 17361)
+++ icecast/branches/kh/icecast/win32/icecast2.iss	2010-08-04 00:59:21 UTC (rev 17362)
@@ -3,7 +3,7 @@
 
 [Setup]
 AppName=Icecast2-KH
-AppVerName=Icecast v2.3.2-kh24
+AppVerName=Icecast v2.3.2-kh25
 AppPublisherURL=http://www.icecast.org
 AppSupportURL=http://www.icecast.org
 AppUpdatesURL=http://www.icecast.org
@@ -13,7 +13,7 @@
 LicenseFile=..\COPYING
 InfoAfterFile=..\README
 OutputDir=.
-OutputBaseFilename=icecast2_win32_v2.3.2-kh24_setup
+OutputBaseFilename=icecast2_win32_v2.3.2-kh25_setup
 WizardImageFile=icecast2logo2.bmp
 WizardImageStretch=no
 VersionInfoVersion=2.3.2
@@ -69,9 +69,3 @@
 Filename: "{app}\icecastService.exe"; Parameters: "remove"
 
 
-
-
-
-
-
-



More information about the commits mailing list