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

karl at svn.xiph.org karl at svn.xiph.org
Fri Mar 27 16:12:53 PDT 2009


Author: karl
Date: 2009-03-27 16:12:53 -0700 (Fri, 27 Mar 2009)
New Revision: 15865

Modified:
   icecast/branches/kh/icecast/NEWS
   icecast/branches/kh/icecast/admin/xspf.xsl
   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/auth.h
   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/client.c
   icecast/branches/kh/icecast/src/connection.c
   icecast/branches/kh/icecast/src/connection.h
   icecast/branches/kh/icecast/src/format_mp3.c
   icecast/branches/kh/icecast/src/format_ogg.c
   icecast/branches/kh/icecast/src/format_vorbis.c
   icecast/branches/kh/icecast/src/fserve.c
   icecast/branches/kh/icecast/src/global.c
   icecast/branches/kh/icecast/src/global.h
   icecast/branches/kh/icecast/src/logging.c
   icecast/branches/kh/icecast/src/slave.c
   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/util.c
   icecast/branches/kh/icecast/src/util.h
   icecast/branches/kh/icecast/src/xslt.c
   icecast/branches/kh/icecast/src/yp.c
   icecast/branches/kh/icecast/win32/icecast2.iss
Log:
bump to kh9, mainly internals cleanups to help sync with trunk


Modified: icecast/branches/kh/icecast/NEWS
===================================================================
--- icecast/branches/kh/icecast/NEWS	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/NEWS	2009-03-27 23:12:53 UTC (rev 15865)
@@ -10,11 +10,24 @@
   max-listener/bandwidth check. slaves can use a different auth to listeners
 . mount can filter out theora content, useful for defining a local relay
   of a theora+vorbis stream to have a vorbis only stream from the same source.
-. stream-auth/handlers options for url authenticator.
+. handlers options for url authenticator.
 
 any extra tags are show in the conf/icecast.xml.dist file
 
 
+2.3.2-kh9
+. allow shoutcast source client auth work via stream_auth url
+. allow for a flash policy file.
+. internal cleanup to help merging into trunk
+. fix vorbis metadata update via url, broken in recent releases. cleanup some metadata
+  updating/logging
+. drop vorbis stream rebuilding back to flush evert half second, in sync with trunk
+. stop false reports of 'not null' in debug logging. no other effect on server
+. limit how often the relay mountpoint "already exists" logs.
+. minor tweaking to the average bitrate calculation
+. remove the internal global time caching, although prevent several time calls if in
+  succession.
+
 2.3.2-kh8
 . fix memory corruption which affected ogg streams.
 . fix for unsupported FBSD/win32 spin locking options. abort on initialisation failure.

Modified: icecast/branches/kh/icecast/admin/xspf.xsl
===================================================================
--- icecast/branches/kh/icecast/admin/xspf.xsl	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/admin/xspf.xsl	2009-03-27 23:12:53 UTC (rev 15865)
@@ -1,5 +1,5 @@
 <!--
-    XSPF xslt stylesheet for Icecast 2.3.1 and above
+    XSPF xslt stylesheet for Icecast 2.3.2 and above
     Copyright (C) 2007 Thomas B. Ruecker, tbr at ruecker-itk.de
 
     This program is free software; you can redistribute it and/or

Modified: icecast/branches/kh/icecast/config.h.vc6
===================================================================
--- icecast/branches/kh/icecast/config.h.vc6	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/config.h.vc6	2009-03-27 23:12:53 UTC (rev 15865)
@@ -95,7 +95,7 @@
 #define PACKAGE_NAME "Icecast"
 
 /* Version number of package */
-#define VERSION "2.3.2-kh8"
+#define VERSION "2.3.2-kh9"
 
 /* Define to the version of this package. */
 #define PACKAGE_VERSION VERSION

Modified: icecast/branches/kh/icecast/configure.in
===================================================================
--- icecast/branches/kh/icecast/configure.in	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/configure.in	2009-03-27 23:12:53 UTC (rev 15865)
@@ -1,4 +1,4 @@
-AC_INIT([Icecast], [2.3.2-kh8], [karl at xiph.org])
+AC_INIT([Icecast], [2.3.2-kh9], [karl at xiph.org])
 
 AC_PREREQ(2.59)
 AC_CONFIG_SRCDIR(src/main.c)
@@ -44,7 +44,7 @@
 AC_TYPE_OFF_T
 
 dnl Checks for library functions.
-AC_CHECK_FUNCS([localtime_r poll atoll strtoll getrlimit gettimeofday ftime])
+AC_CHECK_FUNCS([localtime_r poll atoll strtoll getrlimit gettimeofday ftime fstat])
 AC_SEARCH_LIBS(nanosleep, rt posix4,
         AC_DEFINE(HAVE_NANOSLEEP, 1, [Define if you have nanosleep]))
 XIPH_NET

Modified: icecast/branches/kh/icecast/src/admin.c
===================================================================
--- icecast/branches/kh/icecast/src/admin.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/admin.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -82,6 +82,7 @@
 };
 
 
+static time_t now;
 
 static struct admin_command admin_general[] =
 {
@@ -365,7 +366,7 @@
         /* This is a mount request, but admin user is allowed */
         if (client->authenticated == 0)
         {
-            switch (connection_check_source_pass (client, mount))
+            switch (auth_check_source (client, mount))
             {
                 case 0:
                     break;
@@ -649,7 +650,7 @@
     xmlNewChild (node, NULL, XMLSTR("lag"), XMLSTR(buf));
 
     snprintf (buf, sizeof (buf), "%lu",
-            (unsigned long)(global.time - listener->con->con_time));
+            (unsigned long)(now - listener->con->con_time));
     xmlNewChild (node, NULL, XMLSTR("connected"), XMLSTR(buf));
     if (listener->username)
     {
@@ -672,6 +673,7 @@
 
     thread_mutex_lock (&source->lock);
 
+    now = time(NULL);
     listener = source->active_clients;
     while (listener)
     {
@@ -752,6 +754,7 @@
         client_t *listener;
         thread_mutex_lock (&source->lock);
 
+        now = time(NULL);
         listener = source->active_clients;
         while (listener)
         {
@@ -1028,18 +1031,18 @@
             if (song)
             {
                 plugin->set_tag (plugin, "song", song, charset);
-                INFO2("Metadata on mountpoint %s changed to \"%s\"", source->mount, song);
+                INFO2("Metadata song on mountpoint %s changed to \"%s\"", source->mount, song);
             }
-            else
+            if (artist)
             {
-                if (artist && title)
-                {
-                    plugin->set_tag (plugin, "title", title, charset);
-                    plugin->set_tag (plugin, "artist", artist, charset);
-                    INFO3("Metadata on mountpoint %s changed to \"%s - %s\"",
-                            source->mount, artist, title);
-                }
+                plugin->set_tag (plugin, "artist", artist, charset);
+                INFO2 ("Metadata artist on mountpoint %s changed to \"%s\"", source->mount, artist);
             }
+            if (title)
+            {
+                plugin->set_tag (plugin, "title", title, charset);
+                INFO2 ("Metadata title on mountpoint %s changed to \"%s\"", source->mount, title);
+            }
             /* updates are now done, let them be pushed into the stream */
             plugin->set_tag (plugin, NULL, NULL, NULL);
         }
@@ -1092,7 +1095,7 @@
         if (connection_check_admin_pass (client->parser) == 0)
             same_ip = 0;
 
-    if (source->format && source->format->set_tag)
+    if (same_ip && source->format && source->format->set_tag)
     {
         httpp_set_query_param (client->parser, "mount", client->server_conn->shoutcast_mount);
         source->format->set_tag (source->format, "title", value, NULL);

Modified: icecast/branches/kh/icecast/src/auth.c
===================================================================
--- icecast/branches/kh/icecast/src/auth.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/auth.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -39,11 +39,11 @@
 #define CATMODULE "auth"
 
 
-static spin_t auth_lock;
 static volatile int thread_id;
 
 static void *auth_run_thread (void *arg);
-static int auth_postprocess_listener (auth_client *auth_user);
+static int  auth_postprocess_listener (auth_client *auth_user);
+static void auth_postprocess_source (auth_client *auth_user);
 
 
 void auth_check_http (client_t *client)
@@ -463,7 +463,7 @@
 
         /* 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 = global.time + mountinfo->max_listener_duration;
+            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);
@@ -636,7 +636,7 @@
     else
     {
         DEBUG1 ("on mountpoint %s", mount);
-        source_startup (client, mount, 0);
+        source_startup (client, mount);
     }
 }
 
@@ -827,7 +827,7 @@
     else
     {
         auth->tailp = &auth->head;
-        thread_mutex_create ("auth_t", &auth->lock);
+        thread_mutex_create (&auth->lock);
 
         /* allocate N threads */
         auth->handles = calloc (auth->handlers, sizeof (auth_thread_t));
@@ -906,17 +906,46 @@
 }
 
 
+/* return -1 for failed, 0 for authenticated, 1 for pending
+ */
+int auth_check_source (client_t *client, const char *mount)
+{
+    ice_config_t *config = config_get_config();
+    char *pass = config->source_password;
+    char *user = "source";
+    int ret = -1;
+    mount_proxy *mountinfo = config_find_mount (config, mount);
+
+    do
+    {
+        if (mountinfo)
+        {
+            ret = 1;
+            if (auth_stream_authenticate (client, mount, mountinfo) > 0)
+                break;
+            ret = -1;
+            if (mountinfo->password)
+                pass = mountinfo->password;
+            if (mountinfo->username)
+                user = mountinfo->username;
+        }
+        if (connection_check_pass (client->parser, user, pass) > 0)
+            ret = 0;
+    } while (0);
+    config_release_config();
+    return ret;
+}
+
+
 /* these are called at server start and termination */
 
 void auth_initialise (void)
 {
-    thread_spin_create ("auth lock", &auth_lock);
     thread_id = 0;
 }
 
 void auth_shutdown (void)
 {
-    thread_spin_destroy (&auth_lock);
     INFO0 ("Auth shutdown");
 }
 

Modified: icecast/branches/kh/icecast/src/auth.h
===================================================================
--- icecast/branches/kh/icecast/src/auth.h	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/auth.h	2009-03-27 23:12:53 UTC (rev 15865)
@@ -114,6 +114,7 @@
 
 void auth_add_listener (const char *mount, client_t *client);
 int  auth_release_listener (client_t *client, const char *mount, struct _mount_proxy *mountinfo);
+int  auth_check_source (client_t *client, const char *mount);
 
 void auth_initialise (void);
 void auth_shutdown (void);
@@ -121,19 +122,15 @@
 int auth_get_authenticator (xmlNodePtr node, void *x);
 void    auth_release (auth_t *authenticator);
 
-/* call to send a url request when source starts */
+/* call to trigger an event when a stream starts */
 void auth_stream_start (struct _mount_proxy *mountinfo, const char *mount);
 
-/* call to send a url request when source ends */
+/* call to trigger an event when a stream ends */
 void auth_stream_end (struct _mount_proxy *mountinfo, const char *mount);
 
-/* */
-int auth_stream_authenticate (client_t *client, const char *mount,
-        struct _mount_proxy *mountinfo);
+/* call to trigger an event to authenticate a source client */
+int auth_stream_authenticate (client_t *client, const char *mount, struct _mount_proxy *mountinfo);
 
-/* called from auth thread */
-void auth_postprocess_source (auth_client *auth_user);
-
 void auth_check_http (client_t *client);
 
 #endif

Modified: icecast/branches/kh/icecast/src/auth_htpasswd.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_htpasswd.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/auth_htpasswd.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -352,6 +352,10 @@
         }
     }
 
+#ifdef HAVE_FSYNC
+    fflush (tmp_passwdfile);
+    fsync (fileno (tmp_passwdfile));
+#endif
     fclose(tmp_passwdfile);
     fclose(passwdfile);
 

Modified: icecast/branches/kh/icecast/src/auth_url.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_url.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/auth_url.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -174,7 +174,7 @@
         {
             unsigned int limit = 0;
             sscanf ((char *)ptr+url->timelimit_header_len, "%u\r\n", &limit);
-            client->con->discon_time = global.time + limit;
+            client->con->discon_time = time(NULL) + limit;
         }
         if (strncasecmp (ptr, "icecast-slave: 1", 16) == 0)
             client->is_slave =1;
@@ -218,7 +218,7 @@
     client_t *client = auth_user->client;
     auth_url *url = auth_user->auth->state;
     auth_thread_data *atd = auth_user->thread_data;
-    time_t duration = global.time - client->con->con_time;
+    time_t duration = time(NULL) - client->con->con_time;
     char *username, *password, *mount, *server, *ipaddr;
     const char *qargs;
     char *userpwd = NULL, post [4096];

Modified: icecast/branches/kh/icecast/src/cfgfile.c
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/cfgfile.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -76,7 +76,7 @@
 static int  _parse_root (xmlNodePtr node, ice_config_t *config);
 
 static void create_locks(void) {
-    thread_mutex_create("relay", &_locks.relay_lock);
+    thread_mutex_create(&_locks.relay_lock);
     thread_rwlock_create(&_locks.config_lock);
 }
 

Modified: icecast/branches/kh/icecast/src/client.c
===================================================================
--- icecast/branches/kh/icecast/src/client.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/client.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -101,16 +101,6 @@
     if (client->respcode && client->parser)
         logging_access(client);
 
-#ifdef HAVE_AIO
-    if (aio_cancel (client->con->sock, NULL) == AIO_NOTCANCELED)
-    {
-        const struct aiocb *list = &client->aio;
-        INFO0 ("having to wait for aio cancellation");
-        while (aio_suspend (&list, 1, NULL) < 0)
-            ;
-    }
-#endif
-
     if (client->con)
         connection_close(client->con);
     if (client->parser)

Modified: icecast/branches/kh/icecast/src/connection.c
===================================================================
--- icecast/branches/kh/icecast/src/connection.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/connection.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -76,8 +76,6 @@
 
    Icecast auth style uses HTTP and Basic Authorization.
 */
-#define SHOUTCAST_SOURCE_AUTH 1
-#define ICECAST_SOURCE_AUTH 0
 
 typedef struct client_queue_tag {
     client_t *client;
@@ -100,7 +98,8 @@
     avl_tree *contents;
 } cache_file_contents;
 
-static spin_t _connection_mutex;
+static time_t now;
+static spin_t _connection_lock;
 static volatile unsigned long _current_id = 0;
 static volatile thread_type *conn_tid;
 
@@ -117,9 +116,9 @@
 cache_file_contents useragents;
 
 int connection_running = 0;
+rwlock_t _source_shutdown_rwlock;
 
 static void _handle_connection(void);
-static int check_pass(http_parser_t *parser, const char *user, const char *pass);
 
 static int compare_line (void *arg, void *a, void *b)
 {
@@ -154,8 +153,9 @@
 
 void connection_initialize(void)
 {
-    thread_spin_create("connection", &_connection_mutex);
-    thread_mutex_create("move_clients", &move_clients_mutex);
+    thread_spin_create (&_connection_lock);
+    thread_mutex_create(&move_clients_mutex);
+    thread_rwlock_create(&_source_shutdown_rwlock);
     thread_cond_create(&global.shutdown_cond);
     _req_queue = NULL;
     _req_queue_tail = &_req_queue;
@@ -183,7 +183,10 @@
     if (useragents.contents) avl_tree_free (useragents.contents, free_filtered_line);
 
     thread_cond_destroy(&global.shutdown_cond);
-    thread_spin_destroy(&_connection_mutex);
+    thread_rwlock_wlock(&_source_shutdown_rwlock);
+    thread_rwlock_unlock(&_source_shutdown_rwlock);
+    thread_rwlock_destroy(&_source_shutdown_rwlock);
+    thread_spin_destroy (&_connection_lock);
     thread_mutex_destroy(&move_clients_mutex);
 }
 
@@ -191,9 +194,9 @@
 {
     unsigned long id;
 
-    thread_spin_lock(&_connection_mutex);
+    thread_spin_lock (&_connection_lock);
     id = _current_id++;
-    thread_spin_unlock(&_connection_mutex);
+    thread_spin_unlock (&_connection_lock);
 
     return id;
 }
@@ -314,7 +317,7 @@
  */
 static void recheck_cached_file (cache_file_contents *cache)
 {
-    if (global.time >= cache->file_recheck)
+    if (now >= cache->file_recheck)
     {
         struct stat file_stat;
         FILE *file = NULL;
@@ -322,7 +325,7 @@
         avl_tree *new_ips;
         char line [MAX_LINE_LEN];
 
-        cache->file_recheck = global.time + 10;
+        cache->file_recheck = now + 10;
         if (cache->filename == NULL)
         {
             if (cache->contents)
@@ -413,7 +416,7 @@
         con->serversock = serversock;
         con->read = connection_read;
         con->send = connection_send;
-        con->con_time = global.time;
+        con->con_time = time(NULL);
         con->id = _next_connection_id();
         con->ip = ip;
     }
@@ -525,6 +528,7 @@
     if (serversock == SOCK_ERROR)
         return NULL;
 
+    now = time(NULL);
     /* malloc enough room for a full IP address (including ipv6) */
     ip = (char *)malloc(MAX_ADDR_LEN);
 
@@ -603,7 +607,7 @@
 
         if (len > 0)
         {
-            if (client->con->con_time + timeout <= global.time)
+            if (client->con->con_time + timeout <= now)
                 len = 0;
             else
                 len = client_read_bytes (client, buf, len);
@@ -620,6 +624,10 @@
             client->refbuf->data [node->offset] = '\000';
             do
             {
+                /* ugly hack for flash policy files */
+                if (node->offset == 23 && memcmp (client->refbuf->data, "<policy-file-request/>", 23) == 0)
+                    break;
+
                 if (node->shoutcast == 1)
                 {
                     /* password line */
@@ -699,12 +707,6 @@
     if (client->server_conn->shoutcast_compat)
         node->shoutcast = 1;
 
-    if (sock_set_blocking (client->con->sock, 0) || sock_set_nodelay (client->con->sock))
-    {
-        WARN0 ("failed to set tcp options on client connection, dropping");
-        client->con->error = 1;
-    }
-
     return node;
 }
 
@@ -743,6 +745,13 @@
             /* setup client for reading incoming http */
             client->refbuf->data [PER_CLIENT_REFBUF_SIZE-1] = '\000';
 
+            if (sock_set_blocking (client->con->sock, 0) || sock_set_nodelay (client->con->sock))
+            {
+                WARN0 ("failed to set tcp options on client connection, dropping");
+                client_destroy (client);
+                continue;
+            }
+
             node = _create_req_node (client);
             if (node == NULL)
             {
@@ -858,6 +867,7 @@
         config_release_config();
         slave_rebuild_mounts();
 
+        source->shutdown_rwlock = &_source_shutdown_rwlock;
         DEBUG0 ("source is ready to start");
 
         return 0;
@@ -984,40 +994,10 @@
     return ret;
 }
 
-/* return -1 for failed, 0 for authenticated, 1 for pending
- */
-int connection_check_source_pass (client_t *client, const char *mount)
-{
-    ice_config_t *config = config_get_config();
-    mount_proxy *mountinfo;
-    char *pass = config->source_password;
-    char *user = "source";
-    int ret = -1;
 
-    mountinfo = config_find_mount (config, mount);
-    do
-    {
-        if (mountinfo)
-        {
-            ret = 1;
-            if (auth_stream_authenticate (client, mount, mountinfo) > 0)
-                break;
-            ret = -1;
-            if (mountinfo->password)
-                pass = mountinfo->password;
-            if (mountinfo->username)
-                user = mountinfo->username;
-        }
-        if (check_pass (client->parser, user, pass) > 0)
-            ret = 0;
-    } while (0);
-    config_release_config();
-    return ret;
-}
-
 /* return 0 for failed, 1 for ok
  */
-static int check_pass (http_parser_t *parser, const char *user, const char *pass)
+int connection_check_pass (http_parser_t *parser, const char *user, const char *pass)
 {
     int ret;
     const char *protocol;
@@ -1058,65 +1038,23 @@
         client_send_401 (client, NULL);
         return;
     }
-    switch (connection_check_source_pass (client, uri))
+    switch (auth_check_source (client, uri))
     {
         case 0: /* authenticated from config file */
-            source_startup (client, uri, ICECAST_SOURCE_AUTH);
+            source_startup (client, uri);
             break;
 
         case 1: /* auth pending */
             break;
 
         default: /* failed */
-            /* We commonly get this if the source client is using the wrong
-             * protocol: attempt to diagnose this and return an error
-             */
-            /* TODO: Do what the above comment says */
             INFO1("Source (%s) attempted to login with invalid or missing password", uri);
             client_send_401 (client, NULL);
             break;
     }
 }
 
-void source_startup (client_t *client, const char *uri, int auth_style)
-{
-    source_t *source;
-    source = source_reserve (uri);
-    
-    if (source)
-    {
-        source->client = client;
-        source->parser = client->parser;
-        if (connection_complete_source (source, 1) < 0)
-        {
-            source_clear_source (source);
-            source_free_source (source);
-            return;
-        }
-        client->respcode = 200;
-        if (auth_style == SHOUTCAST_SOURCE_AUTH)
-        {
-            source->shoutcast_compat = 1;
-            source_client_callback (client, source);
-        }
-        else
-        {
-            refbuf_t *ok = refbuf_new (PER_CLIENT_REFBUF_SIZE);
-            snprintf (ok->data, PER_CLIENT_REFBUF_SIZE,
-                    "HTTP/1.0 200 OK\r\n\r\n");
-            ok->len = strlen (ok->data);
-            /* we may have unprocessed data read in, so don't overwrite it */
-            ok->associated = client->refbuf;
-            client->refbuf = ok;
-            fserve_add_client_callback (client, source_client_callback, source);
-        }
-        return;
-    }
-    client_send_403 (client, "Mountpoint in use");
-    WARN1 ("Mountpoint %s in use", uri);
-}
 
-
 static void _handle_stats_request (client_t *client, char *uri)
 {
     if (connection_check_admin_pass (client->parser) == 0)
@@ -1219,104 +1157,40 @@
 
 static void _handle_shoutcast_compatible (client_queue_t *node)
 {
-    char *http_compliant;
-    int http_compliant_len = 0;
-    http_parser_t *parser;
     ice_config_t *config = config_get_config ();
     client_t *client = node->client;
     listener_t *server_conn = client->server_conn;
 
-    if (node->shoutcast == 1)
-    {
-        char *source_password, *ptr, *headers;
-        mount_proxy *mountinfo = config_find_mount (config, server_conn->shoutcast_mount);
+    char *user = "source", *ptr, *headers, *esc_header;
+    mount_proxy *mountinfo = config_find_mount (config, server_conn->shoutcast_mount);
+    refbuf_t *r;
+    int len;
+    char auth [256];
 
-        if (mountinfo && mountinfo->password)
-            source_password = strdup (mountinfo->password);
-        else
-            source_password = strdup (config->source_password);
-        config_release_config();
+    if (mountinfo && mountinfo->username)
+        user = mountinfo->username;
 
-        /* Get rid of trailing \r\n or \n after password */
-        ptr = strstr (client->refbuf->data, "\r\r\n");
-        if (ptr)
-            headers = ptr+3;
-        else
-        {
-            ptr = strstr (client->refbuf->data, "\r\n");
-            if (ptr)
-                headers = ptr+2;
-            else
-            {
-                ptr = strstr (client->refbuf->data, "\n");
-                if (ptr)
-                    headers = ptr+1;
-            }
-        }
-
-        if (ptr == NULL)
-        {
-            client_destroy (client);
-            free (source_password);
-            free (node);
-            return;
-        }
-        *ptr = '\0';
-
-        if (strcmp (client->refbuf->data, source_password) == 0)
-        {
-            client->respcode = 200;
-            /* send this non-blocking but if there is only a partial write
-             * then leave to header timeout */
-            sock_write (client->con->sock, "OK2\r\nicy-caps:11\r\n\r\n");
-            node->offset -= (headers - client->refbuf->data);
-            memmove (client->refbuf->data, headers, node->offset+1);
-            node->shoutcast = 2;
-            /* we've checked the password, now send it back for reading headers */
-            _add_request_queue (node);
-            free (source_password);
-            return;
-        }
-        else
-            INFO1 ("password does not match \"%s\"", client->refbuf->data);
-        client_destroy (client);
-        free (source_password);
-        free (node);
-        return;
-    }
-    /* actually make a copy as we are dropping the config lock */
+    ptr = client->refbuf->data;
+    len = strcspn (ptr, "\r\n");
+    snprintf (auth, sizeof auth, "%s:%.*s", user, len, ptr);
     config_release_config();
-    /* Here we create a valid HTTP request based of the information
-       that was passed in via the non-HTTP style protocol above. This
-       means we can use some of our existing code to handle this case */
-    http_compliant_len = 20 + strlen (server_conn->shoutcast_mount) + node->offset;
-    http_compliant = (char *)calloc(1, http_compliant_len);
-    snprintf (http_compliant, http_compliant_len,
-            "SOURCE %s HTTP/1.0\r\n%s", server_conn->shoutcast_mount, client->refbuf->data);
-    parser = httpp_create_parser();
-    httpp_initialize (parser, NULL);
-    if (httpp_parse (parser, http_compliant, strlen(http_compliant)))
-    {
-        /* we may have more than just headers, so prepare for it */
-        if (node->stream_offset == node->offset)
-            client->refbuf->len = 0;
-        else
-        {
-            char *ptr = client->refbuf->data;
-            client->refbuf->len = node->offset - node->stream_offset;
-            memmove (ptr, ptr + node->stream_offset, client->refbuf->len);
-        }
-        client->parser = parser;
-        source_startup (client, server_conn->shoutcast_mount, SHOUTCAST_SOURCE_AUTH);
-    }
-    else
-    {
-        httpp_destroy (parser);
-        client_destroy (client);
-    }
-    free (http_compliant);
-    free (node);
-    return;
+    ptr += len;
+    headers = ptr + strspn (ptr, "\r\n");
+
+    esc_header = util_base64_encode (auth);
+    sock_write (client->con->sock, "OK2\r\nicy-caps:11\r\n\r\n");
+    /* build a buffer in a way that an icecast2 source client would present as */
+    r = refbuf_new (PER_CLIENT_REFBUF_SIZE);
+    snprintf (r->data, PER_CLIENT_REFBUF_SIZE,
+            "SOURCE %s HTTP/1.0\r\n" "Authorization: Basic %s\r\n%s",
+            server_conn->shoutcast_mount, esc_header, headers);
+    free (esc_header);
+    refbuf_release (client->refbuf);
+    client->refbuf = r;
+    r->len = 0;
+    node->shoutcast = 0;
+    node->offset = strlen (r->data);
+    _add_request_queue (node);
 }
 
 
@@ -1337,6 +1211,13 @@
         {
             client_t *client = node->client;
 
+            if (node->offset == 23 && memcmp (client->refbuf->data, "<policy-file-request/>", 23) == 0)
+            {
+                client->respcode = 200;
+                fserve_client_create (client, "/flashpolicy");
+                free (node);
+                continue;
+            }
             /* Check for special shoutcast compatability processing */
             if (node->shoutcast)
             {

Modified: icecast/branches/kh/icecast/src/connection.h
===================================================================
--- icecast/branches/kh/icecast/src/connection.h	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/connection.h	2009-03-27 23:12:53 UTC (rev 15865)
@@ -24,7 +24,6 @@
 typedef struct connection_tag connection_t;
 
 #include "cfgfile.h"
-#include "client.h"
 #include "compat.h"
 #include "httpp/httpp.h"
 #include "thread/thread.h"
@@ -68,7 +67,7 @@
 void connection_uses_ssl (connection_t *con);
 void connection_thread_shutdown_req (void);
 
-int connection_check_source_pass (client_t *client, const char *mount);
+int connection_check_pass (http_parser_t *parser, const char *user, const char *pass);
 int connection_check_relay_pass(http_parser_t *parser);
 int connection_check_admin_pass(http_parser_t *parser);
 

Modified: icecast/branches/kh/icecast/src/format_mp3.c
===================================================================
--- icecast/branches/kh/icecast/src/format_mp3.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/format_mp3.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -76,6 +76,7 @@
 
     plugin = (format_plugin_t *)calloc(1, sizeof(format_plugin_t));
 
+    plugin->mount = source->mount;
     plugin->type = FORMAT_TYPE_GENERIC;
     plugin->get_buffer = mp3_get_no_meta;
     plugin->write_buf_to_client = format_mp3_write_buf_to_client;
@@ -112,7 +113,7 @@
         }
     }
     source->format = plugin;
-    thread_mutex_create ("mp3 url lock", &state->url_lock);
+    thread_mutex_create (&state->url_lock);
 
     return 0;
 }
@@ -142,13 +143,22 @@
 
     if (strcmp (tag, "title") == 0 || strcmp (tag, "song") == 0)
     {
+        if (*tag == 's')
+        {
+            /* song typically includes artist */
+            free (source_mp3->url_artist);
+            source_mp3->url_artist = NULL;
+            stats_event (plugin->mount, "artist", NULL);
+        }
         free (source_mp3->url_title);
         source_mp3->url_title = value;
+        stats_event (plugin->mount, "title", value);
     }
     else if (strcmp (tag, "artist") == 0)
     {
         free (source_mp3->url_artist);
         source_mp3->url_artist = value;
+        stats_event (plugin->mount, "artist", value);
     }
     else if (strcmp (tag, "url") == 0)
     {
@@ -161,33 +171,27 @@
 }
 
 
-static void filter_shoutcast_metadata (source_t *source, char *metadata, size_t meta_len)
+static char *filter_shoutcast_metadata (source_t *source, char *metadata, size_t meta_len)
 {
-    if (metadata)
+    char *p = NULL;
+    char *end;
+    int len;
+
+    do
     {
-        char *end, *p;
-        int len;
-
-        do
-        {
-            metadata++;
-            if (strncmp (metadata, "StreamTitle='", 13))
-                break;
-            if ((end = strstr (metadata+13, "\';")) == NULL)
-                break;
-            len = (end - metadata) - 13;
-            p = calloc (1, len+1);
-            if (p)
-            {
-                memcpy (p, metadata+13, len);
-
-                stats_event_conv (source->mount, "title", p, source->format->charset);
-
-                yp_touch (source->mount);
-                free (p);
-            }
-        } while (0);
-    }
+        if (metadata == NULL)
+            break;
+        metadata++;
+        if (strncmp (metadata, "StreamTitle='", 13))
+            break;
+        if ((end = strstr (metadata+13, "\';")) == NULL)
+            break;
+        len = (end - metadata) - 13;
+        p = calloc (1, len+1);
+        if (p)
+            memcpy (p, metadata+13, len);
+    } while (0);
+    return p;
 }
 
 
@@ -277,6 +281,7 @@
     {
         mp3_state *source_mp3 = source->format->_state;
         int r;
+        char *title;
 
         memset (p->data, '\0', size);
         if (source_mp3->url_artist && source_mp3->url_title)
@@ -299,7 +304,10 @@
                 snprintf (p->data+r, size-r, "StreamUrl='%s';", source_mp3->url);
         }
         DEBUG1 ("shoutcast metadata block setup with %s", p->data+1);
-        filter_shoutcast_metadata (source, p->data, size);
+        title = filter_shoutcast_metadata (source, p->data, size);
+        logging_playlist (source->mount, title, source->listeners);
+        yp_touch (source->mount);
+        free (title);
 
         refbuf_release (source_mp3->metadata);
         source_mp3->metadata = p;
@@ -510,7 +518,7 @@
             }
             return 0;
         }
-        rate_add (format->in_bitrate, bytes, global.time);
+        rate_add (format->in_bitrate, bytes, time(NULL));
     }
     source_mp3->read_count += bytes;
     refbuf = source_mp3->read_data;
@@ -644,8 +652,12 @@
             DEBUG1("shoutcast metadata %.4080s", meta->data+1);
             if (strncmp (meta->data+1, "StreamTitle=", 12) == 0)
             {
-                filter_shoutcast_metadata (source, source_mp3->build_metadata,
-                        source_mp3->build_metadata_len);
+                char *title = filter_shoutcast_metadata (source,
+                        source_mp3->build_metadata, source_mp3->build_metadata_len);
+                logging_playlist (source->mount, title, source->listeners);
+                stats_event_conv (source->mount, "title", title, source->format->charset);
+                yp_touch (source->mount);
+                free (title);
                 refbuf_release (source_mp3->metadata);
                 source_mp3->metadata = meta;
                 source_mp3->inline_url = strstr (meta->data+1, "StreamUrl='");

Modified: icecast/branches/kh/icecast/src/format_ogg.c
===================================================================
--- icecast/branches/kh/icecast/src/format_ogg.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/format_ogg.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -480,7 +480,7 @@
             return NULL;
         }
         format->read_bytes += bytes;
-        rate_add (format->in_bitrate, bytes, global.time);
+        rate_add (format->in_bitrate, bytes, time(NULL));
         ogg_sync_wrote (&ogg_info->oy, bytes);
     }
 }

Modified: icecast/branches/kh/icecast/src/format_vorbis.c
===================================================================
--- icecast/branches/kh/icecast/src/format_vorbis.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/format_vorbis.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -422,7 +422,6 @@
     ogg_state_t *ogg_info = plugin->_state;
     ogg_codec_t *codec = ogg_info->codecs;
     vorbis_codec_t *source_vorbis;
-    int change = 0;
     char *value;
 
     /* avoid url updates unless allowed to */
@@ -435,6 +434,13 @@
     else
         return;
 
+    if (tag == NULL)
+    {
+        source_vorbis->stream_notify = 1;
+        source_vorbis->rebuild_comment = 1;
+        return;
+    }
+
     value = util_conv_string (in_value, charset, "UTF-8");
     if (value == NULL)
         value = strdup (in_value);
@@ -443,27 +449,17 @@
     {
         free (ogg_info->artist);
         ogg_info->artist = value;
-        change = 1;
     }
     else if (strcmp (tag, "title") == 0)
     {
         free (ogg_info->title);
         ogg_info->title = value;
-        change = 1;
     }
     else if (strcmp (tag, "song") == 0)
     {
-        free (ogg_info->artist);
         free (ogg_info->title);
-        ogg_info->artist = NULL;
         ogg_info->title = value;
-        change = 1;
     }
-    if (change)
-    {
-        source_vorbis->stream_notify = 1;
-        source_vorbis->rebuild_comment = 1;
-    }
     else
         free (value);
 }
@@ -557,8 +553,8 @@
     /* if vorbis is the only codec then allow rebuilding of the streams */
     if (ogg_info->codecs->next == NULL && ogg_info->passthrough == 0)
     {
-        /* set queued vorbis pages to contain about 1 second worth of samples */
-        source_vorbis->page_samples_trigger = (ogg_int64_t)(source_vorbis->vi.rate);
+        /* set queued vorbis pages to contain about 1/2 second worth of samples */
+        source_vorbis->page_samples_trigger = (ogg_int64_t)(source_vorbis->vi.rate/2);
         if (ogg_info->admin_comments_only)
             source_vorbis->rebuild_comment = 1;
         source_vorbis->process_packet = process_vorbis_headers;

Modified: icecast/branches/kh/icecast/src/fserve.c
===================================================================
--- icecast/branches/kh/icecast/src/fserve.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/fserve.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -94,7 +94,9 @@
     ice_config_t *config = config_get_config();
 
     mimetypes = NULL;
-    thread_spin_create ("fserve pending", &pending_lock);
+    active_list = NULL;
+    pending_list = NULL;
+    thread_spin_create (&pending_lock);
 
     fserve_recheck_mime_types (config);
     config_release_config();
@@ -297,6 +299,7 @@
                             continue;
                         }
                         refbuf = refbuf->next;
+                        client->refbuf->next = NULL;
                         refbuf_release (client->refbuf);
                         client->refbuf = refbuf;
                         bytes = refbuf->len;
@@ -323,7 +326,6 @@
             fclient = fclient->next;
         }
     }
-
     DEBUG0 ("fserve handler exit");
     return NULL;
 }
@@ -409,14 +411,17 @@
     const char *range = NULL;
     off_t new_content_len = 0;
     off_t rangenumber = 0, content_length;
-    int ret = 0;
+    int ret = 0, use_admin = 0;
     char *fullpath;
     int m3u_requested = 0, m3u_file_available = 1;
     int xspf_requested = 0, xspf_file_available = 1;
     ice_config_t *config;
     FILE *file;
 
-    fullpath = util_get_path_from_normalised_uri (path);
+    if (httpclient->parser == NULL) /* special case for specific non-http content */
+        use_admin = 1;
+
+    fullpath = util_get_path_from_normalised_uri (path, use_admin);
     INFO2 ("checking for file %s (%s)", path, fullpath);
 
     if (strcmp (util_get_extension (fullpath), "m3u") == 0)
@@ -595,7 +600,7 @@
             else
                 break;
         }
-        else
+        else if (httpclient->parser)
         {
             char *type = fserve_content_type (path);
             httpclient->respcode = 200;
@@ -644,6 +649,7 @@
     thread_spin_unlock (&pending_lock);
 }
 
+
 /* Add client to fserve thread, client needs to have refbuf set and filled
  * but may provide a NULL file if no data needs to be read
  */
@@ -654,7 +660,7 @@
     DEBUG0 ("Adding client to file serving engine");
     if (fclient == NULL)
     {
-        client_send_404 (client, "memory exhausted");
+        client_destroy (client);
         return -1;
     }
     fclient->file = file;

Modified: icecast/branches/kh/icecast/src/global.c
===================================================================
--- icecast/branches/kh/icecast/src/global.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/global.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -41,10 +41,9 @@
     global.running = 0;
     global.clients = 0;
     global.sources = 0;
-    global.time = time(NULL);
     global.source_tree = avl_tree_new(source_compare_sources, NULL);
-    thread_mutex_create("global", &_global_mutex);
-    thread_spin_create ("xyz", &global.spinlock);
+    thread_mutex_create(&_global_mutex);
+    thread_spin_create (&global.spinlock);
     global.out_bitrate = rate_setup (151, 1000);
 }
 
@@ -70,7 +69,7 @@
 void global_add_bitrates (struct rate_calc *rate, unsigned long value)
 {
     thread_spin_lock (&global.spinlock);
-    rate_add (rate, value, global.time_ms);
+    rate_add (rate, value, timing_get_time());
     thread_spin_unlock (&global.spinlock);
 }
 

Modified: icecast/branches/kh/icecast/src/global.h
===================================================================
--- icecast/branches/kh/icecast/src/global.h	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/global.h	2009-03-27 23:12:53 UTC (rev 15865)
@@ -39,9 +39,6 @@
     int clients;
     int schedule_config_reread;
 
-    time_t time;
-    uint64_t time_ms;
-
     avl_tree *source_tree;
     /* for locally defined relays */
     struct _relay_server *relays;

Modified: icecast/branches/kh/icecast/src/logging.c
===================================================================
--- icecast/branches/kh/icecast/src/logging.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/logging.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -44,7 +44,7 @@
     char    sign;
     char    *timezone_string;
     struct tm gmt;
-    time_t time1 = global.time;
+    time_t time1 = time(NULL);
     int time_days, time_hours, time_tz;
     int tempnum1, tempnum2;
     struct tm *thetime;
@@ -81,7 +81,7 @@
     timezone_string = calloc(1, 7);
     snprintf(timezone_string, 7, " %c%.2d%.2d", sign, time_tz / 60, time_tz % 60);
 
-    now = global.time;
+    now = time(NULL);
 
     thetime = localtime(&now);
     strftime (buffer, len-7, "%d/%b/%Y:%H:%M:%S", thetime);
@@ -117,7 +117,7 @@
     if (httpp_getvar (client->parser, "__avoid_access_log"))
         return;
 
-    now = global.time;
+    now = time(NULL);
 
     localtime_r (&now, &thetime);
     /* build the data */
@@ -174,7 +174,7 @@
         return;
     }
 
-    now = global.time;
+    now = time(NULL);
 
     localtime_r (&now, &thetime);
     /* build the data */

Modified: icecast/branches/kh/icecast/src/slave.c
===================================================================
--- icecast/branches/kh/icecast/src/slave.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/slave.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -224,7 +224,7 @@
     while (checking)
     {
         DEBUG2 ("...%s:%d", checking->server, checking->port);
-        if (checking->next_update && checking->next_update+10 < global.time)
+        if (checking->next_update && checking->next_update+10 < time(NULL))
         {
             /* no streamist request, expire slave for now */
             *trail = checking->next;
@@ -469,7 +469,7 @@
             /* only keep refreshing YP entries for inactive on-demand relays */
             yp_remove (relay->localmount);
             relay->source->yp_public = -1;
-            relay->start = global.time + 10; /* prevent busy looping if failing */
+            relay->start = time(NULL) + 10; /* prevent busy looping if failing */
             slave_update_all_mounts();
         }
 
@@ -506,7 +506,7 @@
 
     /* cleanup relay, but prevent this relay from starting up again too soon */
     relay->source->on_demand = 0;
-    relay->start = global.time + relay->interval;
+    relay->start = time(NULL) + relay->interval;
     relay->cleanup = 1;
 
     return NULL;
@@ -531,18 +531,25 @@
             DEBUG1("Adding relay source at mountpoint \"%s\"", relay->localmount);
             if (relay->on_demand)
             {
-                relay->start = global.time;
+                relay->start = time(NULL);
                 slave_update_all_mounts();
             }
         }
         else
-            WARN1 ("new relay but source \"%s\" already exists", relay->localmount);
+        {
+            if (relay->start == 0)
+            {
+                WARN1 ("new relay but source \"%s\" already exists", relay->localmount);
+                relay->start = 1;
+            }
+            return;
+        }
     }
     do
     {
         source_t *source = relay->source;
         /* skip relay if active, not configured or just not time yet */
-        if (relay->source == NULL || relay->running || relay->start > global.time)
+        if (relay->source == NULL || relay->running || relay->start > time(NULL))
             break;
         if (relay->enable == 0)
         {
@@ -587,7 +594,7 @@
                 break;
         }
 
-        relay->start = global.time + 5;
+        relay->start = time(NULL) + 5;
         relay->running = 1;
         relay->thread = thread_create ("Relay Thread", start_relay_stream,
                 relay, THREAD_ATTACHED);
@@ -620,7 +627,7 @@
             thread_mutex_unlock (&relay->source->lock);
             config_release_config ();
             stats_event (relay->localmount, "listeners", "0");
-            relay->start = global.time;
+            relay->start = time(NULL);
         }
     }
 }
@@ -1039,33 +1046,22 @@
     {
         relay_server *cleanup_relays = NULL;
         int skip_timer = 0;
-        uint64_t prev_time_ms = timing_get_time();
 
-        do
+        /* re-read xml file if requested */
+        if (global . schedule_config_reread)
         {
-            /* re-read xml file if requested */
-            if (global . schedule_config_reread)
-            {
-                event_config_read ();
-                global . schedule_config_reread = 0;
-            }
+            event_config_read ();
+            global . schedule_config_reread = 0;
+        }
 
-            if (global.running != ICE_RUNNING)
-                break;
+        thread_sleep (1000000);
+        global_add_bitrates (global.out_bitrate, 0L);
 
-            thread_sleep (100000);
-            global.time_ms = timing_get_time ();
-            global.time = (long)(global.time_ms/(uint64_t)1000);
-
-            global_add_bitrates (global.out_bitrate, 0L);
-        } while (global.time_ms - prev_time_ms < 1000);
-        prev_time_ms = global.time_ms;
-
         if (global.running != ICE_RUNNING)
             break;
 
         /* only update relays lists from master when required */
-        if (streamlist_check <= global.time)
+        if (streamlist_check <= time(NULL))
         {
             ice_config_t *config;
 
@@ -1075,7 +1071,7 @@
             thread_mutex_lock (&(config_locks()->relay_lock));
             config = config_get_config();
 
-            streamlist_check = global.time + config->master_update_interval;
+            streamlist_check = time(NULL) + config->master_update_interval;
             update_master_as_slave (config);
 
             update_from_master (config);
@@ -1179,7 +1175,7 @@
     else
     {
         DEBUG2 ("touch update on %s:%d", redirect->server, redirect->port);
-        redirect->next_update = global.time + interval;
+        redirect->next_update = time(NULL) + interval;
     }
     thread_rwlock_unlock (&slaves_lock);
 }
@@ -1223,7 +1219,7 @@
     if (interval == 0)
         redirect->next_update = (time_t)0;
     else
-        redirect->next_update = global.time + interval;
+        redirect->next_update = time(NULL) + interval;
     redirect->next = redirectors;
     redirectors = redirect;
     global.redirect_count++;

Modified: icecast/branches/kh/icecast/src/source.c
===================================================================
--- icecast/branches/kh/icecast/src/source.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/source.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -99,7 +99,7 @@
         src->avg_bitrate_duration = 60;
         src->listener_send_trigger = 10000;
 
-        thread_mutex_create (src->mount, &src->lock);
+        thread_mutex_create (&src->lock);
 
         avl_insert (global.source_tree, src);
 
@@ -248,6 +248,7 @@
     {
         refbuf_t *to_go = p;
         p = to_go->next;
+        to_go->next = NULL;
         refbuf_release (to_go);
     }
     source->burst_point = NULL;
@@ -257,6 +258,7 @@
     {
         refbuf_t *to_go = p;
         p = to_go->next;
+        to_go->next = NULL;
         if (to_go->_count > 1)
             WARN1 ("buffer is %d", to_go->_count);
         refbuf_release (to_go);
@@ -435,6 +437,7 @@
     unsigned long incoming_rate = 8 * rate_avg (source->format->in_bitrate);
     unsigned long kbytes_sent = source->bytes_sent_since_update/1024;
     unsigned long kbytes_read = source->bytes_read_since_update/1024;
+    time_t now = time(NULL);
 
     source->format->sent_bytes += kbytes_sent*1024;
     stats_event_args (source->mount, "outgoing_kbitrate", "%ld",
@@ -448,7 +451,7 @@
             "%"PRIu64, source->format->sent_bytes/(1024*1024));
     if (source->client)
         stats_event_args (source->mount, "connected", "%"PRIu64,
-                (uint64_t)(global.time - source->client->con->con_time));
+                (uint64_t)(now - source->client->con->con_time));
     stats_event_add (NULL, "stream_kbytes_sent", kbytes_sent);
     stats_event_add (NULL, "stream_kbytes_read", kbytes_read);
 
@@ -470,12 +473,12 @@
             /* if bitrate is consistently excessive then terminate the stream */
             if (source->throttle_termination == 0)
             {
-                source->throttle_termination = global.time + source->avg_bitrate_duration/2;
+                source->throttle_termination = now + source->avg_bitrate_duration/2;
                 /* DEBUG1 ("throttle termination set at %ld", source->throttle_termination); */
             }
             else
             {
-                if (global.time >= source->throttle_termination)
+                if (now >= source->throttle_termination)
                 {
                     source->running = 0;
                     WARN3 ("%s terminating, exceeding bitrate limits (%dk/%dk)",
@@ -504,7 +507,7 @@
     while (global.running == ICE_RUNNING && source->running)
     {
         int fds = 0;
-        time_t current = global.time;
+        time_t current = time(NULL);
         int delay = 200;
 
         source->amount_added_to_queue = 0;
@@ -566,7 +569,7 @@
                 process_listeners (source, 1, 0);
                 continue;
             }
-            rate_add (source->format->in_bitrate, 0, global.time);
+            rate_add (source->format->in_bitrate, 0, current);
             break;
         }
         source->last_read = current;
@@ -645,7 +648,7 @@
     int ret = 0;
 
     /* check for limited listener time */
-    if (client->con->discon_time && global.time >= client->con->discon_time)
+    if (client->con->discon_time && time(NULL) >= client->con->discon_time)
     {
         INFO1 ("time limit reached for client #%lu", client->con->id);
         client->con->error = 1;
@@ -685,7 +688,7 @@
 
         total_written += bytes;
     }
-    rate_add (source->format->out_bitrate, total_written, global.time_ms);
+    rate_add (source->format->out_bitrate, total_written, timing_get_time());
     source->bytes_sent_since_update += total_written;
 
     global_add_bitrates (global.out_bitrate, total_written);
@@ -809,6 +812,9 @@
         }
     }
 
+    /* grab a read lock, to make sure we get a chance to cleanup */
+    thread_rwlock_rlock (source->shutdown_rwlock);
+
     /* start off the statistics */
     stats_event_inc (NULL, "source_total_connections");
     stats_event_hidden (source->mount, "slow_listeners", "0", STATS_COUNTERS);
@@ -822,12 +828,12 @@
     stats_event_hidden (source->mount, "total_bytes_read", "0", STATS_COUNTERS);
 
     DEBUG0("Source creation complete");
-    source->last_read = global.time;
+    source->last_read = time(NULL);
     source->prev_listeners = -1;
     source->bytes_sent_since_update = 0;
     source->stats_interval = 5;
     /* so the first set of average stats after 3 seconds */
-    source->client_stats_update = global.time + 3;
+    source->client_stats_update = source->last_read + 3;
 
     source->fast_clients_p = &source->active_clients;
     source->audio_info = util_dict_new();
@@ -932,6 +938,7 @@
                 }
                 source->stream_data = to_go->next;
                 source->queue_size -= to_go->len;
+                to_go->next = NULL;
                 refbuf_release (to_go);
             }
         }
@@ -998,6 +1005,9 @@
     global.sources--;
     stats_event_args (NULL, "sources", "%d", global.sources);
     global_unlock();
+
+    /* release our hold on the lock so the main thread can continue cleaning up */
+    thread_rwlock_unlock(source->shutdown_rwlock);
 }
 
 
@@ -1077,6 +1087,10 @@
     if (source->format && source->format->apply_settings)
         source->format->apply_settings (source->client, source->format, mountinfo);
 
+    str = httpp_getvar (parser, "user-agent");
+    if (str && source->format)
+        stats_event_conv (source->mount, "user_agent", str, source->format->charset);
+
     /* public */
     if (mountinfo && mountinfo->yp_public >= 0)
         val = mountinfo->yp_public;
@@ -1348,11 +1362,11 @@
 
     if (source->wait_time)
     {
-        time_t release = source->wait_time + global.time;
+        time_t release = source->wait_time + time(NULL);
         INFO2 ("keeping %s reserved for %d seconds", source->mount, source->wait_time);
         thread_mutex_unlock (&source->lock);
-        while (global.running && release >= global.time)
-            thread_sleep (300000);
+        while (global.running && release >= time(NULL))
+            thread_sleep (1000000);
     }
     else
         thread_mutex_unlock (&source->lock);
@@ -1366,7 +1380,6 @@
 
 void source_client_callback (client_t *client, void *arg)
 {
-    const char *agent;
     source_t *source = arg;
     refbuf_t *old_data = client->refbuf;
 
@@ -1383,9 +1396,6 @@
     old_data->associated = NULL;
     refbuf_release (old_data);
     stats_event (source->mount, "source_ip", source->client->con->ip);
-    agent = httpp_getvar (source->client->parser, "user-agent");
-    if (agent)
-        stats_event (source->mount, "user_agent", agent);
 
     thread_create ("Source Thread", source_client_thread,
             source, THREAD_DETACHED);
@@ -1566,3 +1576,45 @@
     config_release_config();
 }
 
+
+void source_startup (client_t *client, const char *uri)
+{
+    source_t *source;
+    source = source_reserve (uri);
+
+    if (source)
+    {
+        source->client = client;
+        source->parser = client->parser;
+        if (connection_complete_source (source, 1) < 0)
+        {
+            source_clear_source (source);
+            source_free_source (source);
+            return;
+        }
+        client->respcode = 200;
+        if (client->server_conn->shoutcast_compat)
+        {
+            source->shoutcast_compat = 1;
+            source_client_callback (client, source);
+        }
+        else
+        {
+            refbuf_t *ok = refbuf_new (PER_CLIENT_REFBUF_SIZE);
+            snprintf (ok->data, PER_CLIENT_REFBUF_SIZE,
+                    "HTTP/1.0 200 OK\r\n\r\n");
+            ok->len = strlen (ok->data);
+            /* we may have unprocessed data read in, so don't overwrite it */
+            ok->associated = client->refbuf;
+            client->refbuf = ok;
+            fserve_add_client_callback (client, source_client_callback, source);
+        }
+    }
+    else
+    {
+        client_send_403 (client, "Mountpoint in use");
+        WARN1 ("Mountpoint %s in use", uri);
+    }
+}
+
+

Modified: icecast/branches/kh/icecast/src/source.h
===================================================================
--- icecast/branches/kh/icecast/src/source.h	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/source.h	2009-03-27 23:12:53 UTC (rev 15865)
@@ -37,6 +37,7 @@
     client_t *active_clients;
     client_t **fast_clients_p;
 
+    rwlock_t *shutdown_rwlock;
     util_dict *audio_info;
 
     /* name of a file, whose contents are sent at listener connection */
@@ -87,7 +88,7 @@
 
 source_t *source_reserve (const char *mount);
 void *source_client_thread (void *arg);
-void source_startup (client_t *client, const char *uri, int auth_style);
+void source_startup (client_t *client, const char *uri);
 void source_client_callback (client_t *client, void *source);
 void source_update_settings (ice_config_t *config, source_t *source, mount_proxy *mountinfo);
 void source_clear_source (source_t *source);

Modified: icecast/branches/kh/icecast/src/stats.c
===================================================================
--- icecast/branches/kh/icecast/src/stats.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/stats.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -152,7 +152,7 @@
     _stats.listeners_removed = NULL;
 
     /* set up global mutex */
-    thread_mutex_create("stats", &_stats_mutex);
+    thread_mutex_create(&_stats_mutex);
 
     _stats_running = 1;
 
@@ -229,17 +229,6 @@
     }
 
     stats_event (mount, name, metadata);
-
-    /* special case for title updates, log converted title */
-    if (mount && strcmp (name, "title") == 0)
-    {
-        char *s = stats_get_value ((char*)mount, "listeners");
-        int listeners = 0;
-        if (s)
-            listeners = atoi (s);
-        free (s);
-        logging_playlist (mount, metadata, listeners);
-    }
     xmlBufferFree (conv);
 }
 
@@ -582,7 +571,7 @@
 
 void stats_event_time (const char *mount, const char *name)
 {
-    time_t now = global.time;
+    time_t now = time(NULL);
     struct tm local;
     char buffer[100];
 
@@ -916,7 +905,7 @@
 void stats_transform_xslt(client_t *client, const char *uri)
 {
     xmlDocPtr doc;
-    char *xslpath = util_get_path_from_normalised_uri (uri);
+    char *xslpath = util_get_path_from_normalised_uri (uri, 0);
     const char *mount = httpp_get_query_param (client->parser, "mount");
 
     doc = stats_get_xml (STATS_PUBLIC, mount);
@@ -1074,14 +1063,9 @@
 void stats_global_calc (void)
 {
     event_listener_t *listener;
-    static time_t next_update = 0;
     stats_event_t event;
     char buffer [VAL_BUFSIZE];
 
-    if (global.time < next_update)
-        return;
-
-    next_update = global.time + 2;
     build_event (&event, NULL, "outgoing_kbitrate", buffer);
     event.hidden = STATS_COUNTERS|STATS_HIDDEN;
 

Modified: icecast/branches/kh/icecast/src/util.c
===================================================================
--- icecast/branches/kh/icecast/src/util.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/util.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -97,7 +97,7 @@
 #endif
 }
 
-int util_read_header(int sock, char *buff, unsigned long len, int entire)
+int util_read_header(sock_t sock, char *buff, unsigned long len, int entire)
 {
     int read_bytes, ret;
     unsigned long pos;
@@ -232,22 +232,26 @@
     if(!path)
         return NULL;
     else {
-        fullpath = util_get_path_from_normalised_uri(path);
+        fullpath = util_get_path_from_normalised_uri(path, 0);
         free(path);
         return fullpath;
     }
 }
 
-char *util_get_path_from_normalised_uri(const char *uri) {
+char *util_get_path_from_normalised_uri(const char *uri, int use_admin)
+{
     char *fullpath;
-    char *webroot;
+    char *root;
     ice_config_t *config = config_get_config();
 
-    webroot = config->webroot_dir;
+    if (use_admin)
+        root = config->adminroot_dir;
+    else
+        root = config->webroot_dir;
 
-    fullpath = malloc(strlen(uri) + strlen(webroot) + 1);
+    fullpath = malloc(strlen(uri) + strlen(root) + 1);
     if (fullpath)
-        sprintf (fullpath, "%s%s", webroot, uri);
+        sprintf (fullpath, "%s%s", root, uri);
     config_release_config();
 
     return fullpath;
@@ -715,11 +719,11 @@
  */
 void rate_add (struct rate_calc *calc, long value, uint64_t sid) 
 {
+    calc->total += value;
     if (calc->current == NULL || sid != calc->current->index)
     {
         if (calc->blocks == calc->samples)
         {
-            calc->total += calc->current->value;
             calc->current = calc->current->next;
             calc->total -= calc->current->value;
             calc->current->value = value;
@@ -735,7 +739,6 @@
             {
                 node->next = calc->current->next;
                 calc->current->next = node;
-                calc->total += calc->current->value;
             }
             else
             {
@@ -756,10 +759,10 @@
 
     if (calc == NULL || calc->blocks < 2)
         return 0;
-    range = (calc->current->index - calc->current->next->index) / calc->ssec;
+    range = (calc->current->index - calc->current->next->index);
     if (range < 1)
         range = 1;
-    return (long)(calc->total / range);
+    return (long)(calc->total / range * calc->ssec);
 }
 
 /* reduce the samples used to calculate average */

Modified: icecast/branches/kh/icecast/src/util.h
===================================================================
--- icecast/branches/kh/icecast/src/util.h	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/util.h	2009-03-27 23:12:53 UTC (rev 15865)
@@ -23,13 +23,12 @@
 
 #define MAX_LINE_LEN 512
 
-
 int util_timed_wait_for_fd(sock_t fd, int timeout);
-int util_read_header(int sock, char *buff, unsigned long len, int entire);
+int util_read_header(sock_t sock, char *buff, unsigned long len, int entire);
 int util_check_valid_extension(const char *uri);
 char *util_get_extension(const char *path);
 char *util_get_path_from_uri(char *uri);
-char *util_get_path_from_normalised_uri(const char *uri);
+char *util_get_path_from_normalised_uri(const char *uri, int use_admin);
 char *util_normalise_uri(const char *uri);
 char *util_base64_encode(const char *data);
 char *util_base64_decode(const char *input);

Modified: icecast/branches/kh/icecast/src/xslt.c
===================================================================
--- icecast/branches/kh/icecast/src/xslt.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/xslt.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -93,7 +93,7 @@
 void xslt_initialize(void)
 {
     memset(cache, 0, sizeof(stylesheet_cache_t)*CACHESIZE);
-    thread_mutex_create("xslt", &xsltlock);
+    thread_mutex_create(&xsltlock);
     xmlInitParser();
     LIBXML_TEST_VERSION
     xmlSubstituteEntitiesDefault(1);

Modified: icecast/branches/kh/icecast/src/yp.c
===================================================================
--- icecast/branches/kh/icecast/src/yp.c	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/src/yp.c	2009-03-27 23:12:53 UTC (rev 15865)
@@ -272,7 +272,7 @@
 {
     ice_config_t *config = config_get_config();
     thread_rwlock_create (&yp_lock);
-    thread_mutex_create ("yp", &yp_pending_lock);
+    thread_mutex_create (&yp_pending_lock);
     yp_recheck_config (config);
     config_release_config ();
 }
@@ -408,7 +408,7 @@
     {
         yp->process = do_yp_touch;
         /* force first touch in 5 secs */
-        yp->next_update = global.time + 5;
+        yp->next_update = time(NULL) + 5;
     }
     return ret;
 }
@@ -524,7 +524,7 @@
     yp = server->mounts;
     while (yp)
     {
-        now = global.time;
+        now = time(NULL);
         /* if one of the streams shows that the server cannot be contacted then mark the
          * other entries for an update later. Assume YP server is dead and skip it for now
          */
@@ -875,7 +875,7 @@
                 yp->server = server;
                 yp->touch_interval = server->touch_interval;
                 yp->next = server->pending_mounts;
-                yp->next_update = global.time + 60;
+                yp->next_update = time(NULL) + 60;
                 server->pending_mounts = yp;
                 yp_update = 1;
             }

Modified: icecast/branches/kh/icecast/win32/icecast2.iss
===================================================================
--- icecast/branches/kh/icecast/win32/icecast2.iss	2009-03-27 23:09:45 UTC (rev 15864)
+++ icecast/branches/kh/icecast/win32/icecast2.iss	2009-03-27 23:12:53 UTC (rev 15865)
@@ -3,7 +3,7 @@
 
 [Setup]
 AppName=Icecast2-KH
-AppVerName=Icecast v2.3.2-kh8
+AppVerName=Icecast v2.3.2-kh9
 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-kh8_setup
+OutputBaseFilename=icecast2_win32_v2.3.2-kh9_setup
 WizardImageFile=icecast2logo2.bmp
 WizardImageStretch=no
 ; uncomment the following line if you want your installation to run on NT 3.51 too.
@@ -42,6 +42,7 @@
 Source: "..\web\images\*.jpg"; DestDir: "{app}\web\images"; Flags: ignoreversion
 Source: "..\web\*.css"; DestDir: "{app}\web"; Flags: ignoreversion
 Source: "..\admin\*.xsl"; DestDir: "{app}\admin"; Flags: ignoreversion
+Source: "..\admin\flashpolicy"; DestDir: "{app}\admin"; Flags: ignoreversion
 Source: "c:\xiph\lib\pthreadVSE.dll"; DestDir: "{app}"; Flags: ignoreversion
 Source: "..\conf\*.dist"; DestDir: "{app}"; Flags: ignoreversion
 Source: "..\examples\icecast_shoutcast_compat.xml"; DestDir: "{app}"; DestName: "icecast.xml"; Flags: ignoreversion



More information about the commits mailing list