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

karl at svn.xiph.org karl at svn.xiph.org
Thu Nov 24 18:54:27 PST 2005


Author: karl
Date: 2005-11-24 18:54:14 -0800 (Thu, 24 Nov 2005)
New Revision: 10429

Modified:
   icecast/branches/kh/icecast/conf/icecast.xml.in
   icecast/branches/kh/icecast/doc/icecast2_config_file.html
   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_url.c
   icecast/branches/kh/icecast/src/cfgfile.c
   icecast/branches/kh/icecast/src/cfgfile.h
   icecast/branches/kh/icecast/src/client.c
   icecast/branches/kh/icecast/src/client.h
   icecast/branches/kh/icecast/src/connection.c
   icecast/branches/kh/icecast/src/format_vorbis.c
   icecast/branches/kh/icecast/src/logging.c
   icecast/branches/kh/icecast/src/main.c
   icecast/branches/kh/icecast/src/source.c
   icecast/branches/kh/icecast/src/source.h
   icecast/branches/kh/icecast/src/stats.c
Log:
mainly sync-up with post 2.3 commits, some minor changes included as well


Modified: icecast/branches/kh/icecast/conf/icecast.xml.in
===================================================================
--- icecast/branches/kh/icecast/conf/icecast.xml.in	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/conf/icecast.xml.in	2005-11-25 02:54:14 UTC (rev 10429)
@@ -181,6 +181,13 @@
         <errorlog>error.log</errorlog>
         <!-- <playlistlog>playlist.log</playlistlog> -->
       	<loglevel>4</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
+      	<logsize>10000</logsize> <!-- Max size of a logfile -->
+        <!-- If logarchive is enabled (1), then when logsize is reached
+             the logfile will be moved to [error|access|playlist].log.DATESTAMP,
+             otherwise it will be moved to [error|access|playlist].log.old.
+             Default is non-archive mode (i.e. overwrite)
+        -->
+        <!-- <logarchive>1</logarchive> -->
     </logging>
 
     <security>

Modified: icecast/branches/kh/icecast/doc/icecast2_config_file.html
===================================================================
--- icecast/branches/kh/icecast/doc/icecast2_config_file.html	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/doc/icecast2_config_file.html	2005-11-25 02:54:14 UTC (rev 10429)
@@ -657,6 +657,18 @@
 <div class="indentedbox">
 Into this file, a log of all metadata for each mountpoint will be written.  The format of the logfile will most likely change over time as we narrow in on a standard format for this.  Currently, the file is pipe delimited.  This option is optional and can be removed entirely from the config file.
 </div>
+<h4>logsize</h4>
+<div class="indentedbox">
+This value specifies (in Kbytes) the maxmimum size of any of the log files.  When the logfile grows beyond this value,
+icecast will either rename it to logfile.old, or add a timestamp to the archived file (if logarchive is enabled).
+</div>
+<h4>logarchive</h4>
+<div class="indentedbox">
+If this value is set, then icecast will append a timestamp to the end of the logfile name when logsize has been reached.
+If disabled, then the default behavior is to rename the logfile to logfile.old (overwriting any previously saved
+logfiles).  We disable this by default to prevent the filling up of filesystems for people who don't care (or know) that 
+their logs are growing.
+</div>
 <h4>loglevel</h4>
 <div class="indentedbox">
 Indicates what messages are logged by icecast.  Log messages are categorized into one of 4 types, Debug, Info, Warn, and Error.<br /><br />The following mapping can be used to set the appropraite value :

Modified: icecast/branches/kh/icecast/src/admin.c
===================================================================
--- icecast/branches/kh/icecast/src/admin.c	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/src/admin.c	2005-11-25 02:54:14 UTC (rev 10429)
@@ -967,7 +967,6 @@
     doc = xmlNewDoc("1.0");
     node = xmlNewDocNode(doc, NULL, "iceresponse", NULL);
     xmlDocSetRootElement(doc, node);
-    DEBUG1("Response is %d", response);
 
     if(listener != NULL) {
         INFO1("Admin request: client %d removed", id);
@@ -976,8 +975,7 @@
          * loop
          */
         listener->con->error = 1;
-        memset(buf, '\000', sizeof(buf));
-        snprintf(buf, sizeof(buf)-1, "Client %d removed", id);
+        snprintf(buf, sizeof(buf), "Client %d removed", id);
         xmlNewChild(node, NULL, "message", buf);
         xmlNewChild(node, NULL, "return", "1");
     }

Modified: icecast/branches/kh/icecast/src/auth.c
===================================================================
--- icecast/branches/kh/icecast/src/auth.c	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/src/auth.c	2005-11-25 02:54:14 UTC (rev 10429)
@@ -122,13 +122,14 @@
     if (authenticator->free)
         authenticator->free (authenticator);
     xmlFree (authenticator->type);
+    xmlFree (authenticator->realm);
     thread_mutex_unlock (&authenticator->lock);
     thread_mutex_destroy (&authenticator->lock);
     free (authenticator);
 }
 
 
-void auth_client_free (auth_client *auth_user)
+static void auth_client_free (auth_client *auth_user)
 {
     if (auth_user == NULL)
         return;
@@ -157,11 +158,7 @@
     if (client->auth->authenticate)
     {
         if (client->auth->authenticate (auth_user) != AUTH_OK)
-        {
-            auth_release (client->auth);
-            client->auth = NULL;
             return;
-        }
     }
     if (auth_postprocess_client (auth_user) < 0)
         INFO1 ("client %lu failed", client->con->id);
@@ -179,7 +176,6 @@
         client->auth->release_client (auth_user);
     auth_release (client->auth);
     client->auth = NULL;
-    return;
 }
 
 
@@ -238,8 +234,17 @@
         existing = source->active_clients;
         while (existing)
         {
-            if (existing->username && strcmp (existing->username, client->username) == 0)
-                return 0;
+            if (existing->con->error == 0 && existing->username &&
+                    strcmp (existing->username, client->username) == 0)
+            {
+                if (auth->drop_existing_listener)
+                {
+                    existing->con->error = 1;
+                    return 1;
+                }
+                else
+                    return 0;
+            }
             existing = existing->next;
         }
     }
@@ -390,7 +395,7 @@
     if (mountinfo && mountinfo->no_mount)
     {
         config_release_config ();
-        client_send_404 (client, "mountpoint unavailable");
+        client_send_403 (client, "mountpoint unavailable");
         return;
     }
     if (mountinfo && mountinfo->auth)
@@ -401,7 +406,7 @@
         {
             config_release_config ();
             WARN0 ("too many clients awaiting authentication");
-            client_send_404 (client, "busy, please try again later");
+            client_send_403 (client, "busy, please try again later");
             return;
         }
         auth_client_setup (mountinfo, client);
@@ -415,7 +420,8 @@
         auth_user = calloc (1, sizeof (auth_client));
         if (auth_user == NULL)
         {
-            client_send_401 (client);
+            ERROR0 ("memory exhausted");
+            abort ();
             return;
         }
         auth_user->mount = strdup (mount);
@@ -430,7 +436,7 @@
         int ret = add_authenticated_client (mount, mountinfo, client);
         config_release_config ();
         if (ret < 0)
-            client_send_404 (client, "stream full");
+            client_send_404 (client, "max listeners reached");
     }
 }
 
@@ -440,7 +446,7 @@
  */
 int release_client (client_t *client)
 {
-    if (client->auth)
+    if (client->auth && client->authenticated)
     {
         auth_client *auth_user = calloc (1, sizeof (auth_client));
         if (auth_user == NULL)
@@ -494,6 +500,10 @@
     {
         if (strcmp(options->name, "allow_duplicate_users") == 0)
             auth->allow_duplicate_users = atoi (options->value);
+        else if (strcmp(options->name, "realm") == 0)
+            auth->realm = xmlStrdup (options->value);
+        else if (strcmp(options->name, "drop_existing_listener") == 0)
+            auth->drop_existing_listener = atoi (options->value);
         options = options->next;
     }
 }

Modified: icecast/branches/kh/icecast/src/auth.h
===================================================================
--- icecast/branches/kh/icecast/src/auth.h	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/src/auth.h	2005-11-25 02:54:14 UTC (rev 10429)
@@ -68,9 +68,11 @@
     mutex_t lock;
     int refcount;
     int allow_duplicate_users;
+    int drop_existing_listener;
 
     void *state;
     char *type;
+    char *realm;
 } auth_t;
 
 void add_client (const char *mount, client_t *client);

Modified: icecast/branches/kh/icecast/src/auth_url.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_url.c	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/src/auth_url.c	2005-11-25 02:54:14 UTC (rev 10429)
@@ -86,6 +86,7 @@
     int  auth_header_len;
     char *timelimit_header;
     int  timelimit_header_len;
+    char *userpwd;
     CURL *handle;
     char errormsg [CURL_ERROR_SIZE];
 } auth_url;
@@ -106,10 +107,19 @@
     free (url->stream_end);
     free (url->auth_header);
     free (url->timelimit_header);
+    free (url->userpwd);
     free (url);
 }
 
 
+/* make sure that prompting at the console does not occur */
+static int my_getpass(void *client, char *prompt, char *buffer, int buflen)
+{
+    buffer[0] = '\0';
+    return 0;
+}
+
+
 static int handle_returned_header (void *ptr, size_t size, size_t nmemb, void *stream)
 {
     auth_client *auth_user = stream;
@@ -159,7 +169,7 @@
     char *username, *password, *mount, *server;
     ice_config_t *config;
     int port;
-    char post [4096];
+    char *userpwd = NULL, post [4096];
 
     if (url->removeurl == NULL)
         return AUTH_OK;
@@ -194,6 +204,29 @@
     free (username);
     free (password);
 
+    if (strchr (url->removeurl, '@') == NULL)
+    {
+        if (url->userpwd)
+            curl_easy_setopt (url->handle, CURLOPT_USERPWD, url->userpwd);
+        else
+        {
+            /* auth'd requests may not have a user/pass, but may use query args */
+            if (client->username && client->password)
+            {
+                int len = strlen (client->username) + strlen (client->password) + 2;
+                userpwd = malloc (len);
+                snprintf (userpwd, len, "%s:%s", client->username, client->password);
+                curl_easy_setopt (url->handle, CURLOPT_USERPWD, userpwd);
+            }
+            else
+                curl_easy_setopt (url->handle, CURLOPT_USERPWD, "");
+        }
+    }
+    else
+    {
+        /* url has user/pass but libcurl may need to clear any existing settings */
+        curl_easy_setopt (url->handle, CURLOPT_USERPWD, "");
+    }
     curl_easy_setopt (url->handle, CURLOPT_URL, url->removeurl);
     curl_easy_setopt (url->handle, CURLOPT_POSTFIELDS, post);
     curl_easy_setopt (url->handle, CURLOPT_WRITEHEADER, auth_user);
@@ -201,6 +234,8 @@
     if (curl_easy_perform (url->handle))
         WARN2 ("auth to server %s failed with %s", url->removeurl, url->errormsg);
 
+    free (userpwd);
+
     return AUTH_OK;
 }
 
@@ -214,7 +249,7 @@
     char *agent, *user_agent, *username, *password;
     char *mount, *ipaddr, *server;
     ice_config_t *config;
-    char post [4096];
+    char *userpwd = NULL, post [4096];
 
     if (url->addurl == NULL)
         return AUTH_OK;
@@ -255,6 +290,29 @@
     free (password);
     free (ipaddr);
 
+    if (strchr (url->addurl, '@') == NULL)
+    {
+        if (url->userpwd)
+            curl_easy_setopt (url->handle, CURLOPT_USERPWD, url->userpwd);
+        else
+        {
+            /* auth'd requests may not have a user/pass, but may use query args */
+            if (client->username && client->password)
+            {
+                int len = strlen (client->username) + strlen (client->password) + 2;
+                userpwd = malloc (len);
+                snprintf (userpwd, len, "%s:%s", client->username, client->password);
+                curl_easy_setopt (url->handle, CURLOPT_USERPWD, userpwd);
+            }
+            else
+                curl_easy_setopt (url->handle, CURLOPT_USERPWD, "");
+        }
+    }
+    else
+    {
+        /* url has user/pass but libcurl may need to clear any existing settings */
+        curl_easy_setopt (url->handle, CURLOPT_USERPWD, "");
+    }
     curl_easy_setopt (url->handle, CURLOPT_URL, url->addurl);
     curl_easy_setopt (url->handle, CURLOPT_POSTFIELDS, post);
     curl_easy_setopt (url->handle, CURLOPT_WRITEHEADER, auth_user);
@@ -262,6 +320,8 @@
 
     res = curl_easy_perform (url->handle);
 
+    free (userpwd);
+
     if (res)
     {
         WARN2 ("auth to server %s failed with %s", url->addurl, url->errormsg);
@@ -308,6 +368,15 @@
     free (server);
     free (mount);
 
+    if (strchr (url->stream_start, '@') == NULL)
+    {
+        if (url->userpwd)
+            curl_easy_setopt (url->handle, CURLOPT_USERPWD, url->userpwd);
+        else
+            curl_easy_setopt (url->handle, CURLOPT_USERPWD, "");
+    }
+    else
+        curl_easy_setopt (url->handle, CURLOPT_USERPWD, "");
     curl_easy_setopt (url->handle, CURLOPT_URL, stream_start_url);
     curl_easy_setopt (url->handle, CURLOPT_POSTFIELDS, post);
     curl_easy_setopt (url->handle, CURLOPT_WRITEHEADER, auth_user);
@@ -351,7 +420,16 @@
     free (server);
     free (mount);
 
-    curl_easy_setopt (url->handle, CURLOPT_URL, stream_end_url);
+    if (strchr (url->stream_end, '@') == NULL)
+    {
+        if (url->userpwd)
+            curl_easy_setopt (url->handle, CURLOPT_USERPWD, url->userpwd);
+        else
+            curl_easy_setopt (url->handle, CURLOPT_USERPWD, "");
+    }
+    else
+        curl_easy_setopt (url->handle, CURLOPT_USERPWD, "");
+    curl_easy_setopt (url->handle, CURLOPT_URL, url->stream_end);
     curl_easy_setopt (url->handle, CURLOPT_POSTFIELDS, post);
     curl_easy_setopt (url->handle, CURLOPT_WRITEHEADER, auth_user);
 
@@ -440,8 +518,16 @@
     curl_easy_setopt (url_info->handle, CURLOPT_WRITEDATA, url_info->handle);
     curl_easy_setopt (url_info->handle, CURLOPT_NOSIGNAL, 1L);
     curl_easy_setopt (url_info->handle, CURLOPT_TIMEOUT, 15L);
+    curl_easy_setopt (url_info->handle, CURLOPT_PASSWDFUNCTION, my_getpass);
     curl_easy_setopt (url_info->handle, CURLOPT_ERRORBUFFER, &url_info->errormsg[0]);
 
+    if (url_info->username && url_info->password)
+    {
+        int len = strlen (url_info->username) + strlen (url_info->password) + 2;
+        url_info->userpwd = malloc (len);
+        snprintf (url_info->userpwd, len, "%s:%s", url_info->username, url_info->password);
+    }
+
     authenticator->state = url_info;
     INFO0("URL based authentication setup");
     return 0;

Modified: icecast/branches/kh/icecast/src/cfgfile.c
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.c	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/src/cfgfile.c	2005-11-25 02:54:14 UTC (rev 10429)
@@ -513,10 +513,6 @@
             tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
             configuration->queue_size_limit = atoi(tmp);
             if (tmp) xmlFree(tmp);
-        } else if (strcmp(node->name, "threadpool") == 0) {
-            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
-            configuration->threadpool_size = atoi(tmp);
-            if (tmp) xmlFree(tmp);
         } else if (strcmp(node->name, "client-timeout") == 0) {
             tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
             configuration->client_timeout = atoi(tmp);
@@ -524,6 +520,8 @@
         } else if (strcmp(node->name, "header-timeout") == 0) {
             tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
             configuration->header_timeout = atoi(tmp);
+            if (configuration->header_timeout < 0 || configuration->header_timeout > 60)
+                configuration->header_timeout = CONFIG_DEFAULT_HEADER_TIMEOUT;
             if (tmp) xmlFree(tmp);
         } else if (strcmp(node->name, "source-timeout") == 0) {
             tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
@@ -991,6 +989,10 @@
            char *tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
            configuration->loglevel = atoi(tmp);
            if (tmp) xmlFree(tmp);
+        } else if (strcmp(node->name, "logarchive") == 0) {
+            char *tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+            configuration->logarchive = atoi(tmp);
+            if (tmp) xmlFree(tmp);
         }
     } while ((node = node->next));
 }

Modified: icecast/branches/kh/icecast/src/cfgfile.h
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.h	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/src/cfgfile.h	2005-11-25 02:54:14 UTC (rev 10429)
@@ -162,6 +162,7 @@
     char *playlist_log;
     int loglevel;
     int logsize;
+    int logarchive;
 
     int chroot;
     int chuid;

Modified: icecast/branches/kh/icecast/src/client.c
===================================================================
--- icecast/branches/kh/icecast/src/client.c	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/src/client.c	2005-11-25 02:54:14 UTC (rev 10429)
@@ -189,6 +189,17 @@
     fserve_add_client (client, NULL);
 }
 
+void client_send_403(client_t *client, const char *reason)
+{
+    if (reason == NULL)
+        reason = "Forbidden";
+    snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
+            "HTTP/1.0 403 %s\r\n\r\n", reason);
+    client->respcode = 403;
+    client->refbuf->len = strlen (client->refbuf->data);
+    fserve_add_client (client, NULL);
+}
+
 void client_send_404(client_t *client, char *message) {
 
     snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
@@ -201,13 +212,19 @@
 }
 
 
-void client_send_401(client_t *client) {
+void client_send_401 (client_t *client)
+{
+    const char *send_realm = ICECAST_VERSION_STRING;
+    if (client->auth && client->auth->realm)
+        send_realm = client->auth->realm;
     snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
             "HTTP/1.0 401 Authentication Required\r\n"
-            "WWW-Authenticate: Basic realm=\"Icecast2 Server\"\r\n"
+            "WWW-Authenticate: Basic realm=\"%s\"\r\n"
             "\r\n"
-            "You need to authenticate\r\n");
+            "You need to authenticate\r\n", send_realm);
     client->respcode = 401;
+    auth_release (client->auth);
+    client->auth = NULL;
     client->refbuf->len = strlen (client->refbuf->data);
     fserve_add_client (client, NULL);
 }

Modified: icecast/branches/kh/icecast/src/client.h
===================================================================
--- icecast/branches/kh/icecast/src/client.h	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/src/client.h	2005-11-25 02:54:14 UTC (rev 10429)
@@ -89,6 +89,7 @@
 void client_send_416(client_t *client);
 void client_send_404(client_t *client, char *message);
 void client_send_401(client_t *client);
+void client_send_403(client_t *client, const char *reason);
 void client_send_400(client_t *client, char *message);
 void client_send_302(client_t *client, char *location);
 int client_send_bytes (client_t *client, const void *buf, unsigned len);

Modified: icecast/branches/kh/icecast/src/connection.c
===================================================================
--- icecast/branches/kh/icecast/src/connection.c	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/src/connection.c	2005-11-25 02:54:14 UTC (rev 10429)
@@ -574,7 +574,7 @@
             if (client_create (&client, con, NULL) < 0)
             {
                 global_unlock();
-                client_send_404 (client, "Icecast connection limit reached");
+                client_send_403 (client, "Icecast connection limit reached");
                 /* don't be too eager as this is an imposed hard limit */
                 thread_sleep (400000);
                 continue;
@@ -655,7 +655,7 @@
                 config_release_config();
                 if (response)
                 {
-                    client_send_404 (source->client, "Content-type not supported");
+                    client_send_403 (source->client, "Content-type not supported");
                     source->client = NULL;
                 }
                 WARN1("Content-type \"%s\" not supported, dropping source", contenttype);
@@ -675,7 +675,7 @@
             config_release_config();
             if (response)
             {
-                client_send_404 (source->client, "internal format allocation problem");
+                client_send_403 (source->client, "internal format allocation problem");
                 source->client = NULL;
             }
             WARN1 ("plugin format failed for \"%s\"", source->mount);
@@ -706,7 +706,7 @@
 
     if (response)
     {
-        client_send_404 (source->client, "too many sources connected");
+        client_send_403 (source->client, "too many sources connected");
         source->client = NULL;
     }
 
@@ -915,7 +915,7 @@
     }
     else
     {
-        client_send_404 (client, "Mountpoint in use");
+        client_send_403 (client, "Mountpoint in use");
         WARN1 ("Mountpoint %s in use", uri);
     }
 }

Modified: icecast/branches/kh/icecast/src/format_vorbis.c
===================================================================
--- icecast/branches/kh/icecast/src/format_vorbis.c	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/src/format_vorbis.c	2005-11-25 02:54:14 UTC (rev 10429)
@@ -42,12 +42,14 @@
 
     int rebuild_comment;
     int stream_notify;
+    int initial_audio_page;
 
     ogg_stream_state new_os;
     int page_samples_trigger;
     ogg_int64_t prev_granulepos;
     ogg_packet *prev_packet;
     ogg_int64_t granulepos;
+    ogg_int64_t initial_page_granulepos;
     ogg_int64_t samples_in_page;
     int prev_window;
     int initial_audio_packet;
@@ -216,10 +218,10 @@
 /* push last packet into stream marked with eos */
 static void initiate_flush (vorbis_codec_t *source_vorbis)
 {
-    DEBUG0 ("adding EOS packet");
     if (source_vorbis->prev_packet)
     {
         /* insert prev_packet with eos */
+        DEBUG0 ("adding EOS packet");
         source_vorbis->prev_packet->e_o_s = 1;
         add_audio_packet (source_vorbis, source_vorbis->prev_packet);
         source_vorbis->prev_packet->e_o_s = 0;
@@ -256,7 +258,25 @@
 
             add_audio_packet (source_vorbis, prev_packet);
             free_ogg_packet (prev_packet);
-            packet . granulepos = source_vorbis->granulepos;
+
+            /* check for short values on first initial page */
+            if (packet . packetno == 4)
+            {
+                if (source_vorbis->initial_page_granulepos < source_vorbis->granulepos)
+                {
+                    source_vorbis->granulepos -= source_vorbis->initial_page_granulepos;
+                    source_vorbis->samples_in_page = source_vorbis->page_samples_trigger;
+                }
+            }
+            /* check for long values on first page */
+            if (packet.granulepos == source_vorbis->initial_page_granulepos)
+            {
+                if (source_vorbis->initial_page_granulepos > source_vorbis->granulepos)
+                    source_vorbis->granulepos = source_vorbis->initial_page_granulepos;
+            }
+
+            if (packet.e_o_s == 0)
+                packet . granulepos = source_vorbis->granulepos;
         }
         else
         {
@@ -497,7 +517,14 @@
         return NULL;
     }
     if (codec->headers == 3)
+    {
+        if (source_vorbis->initial_audio_page)
+        {
+            source_vorbis->initial_page_granulepos = ogg_page_granulepos (page);
+            source_vorbis->initial_audio_page = 0;
+        }
         return NULL;
+    }
 
     while (codec->headers < 3)
     {
@@ -530,6 +557,7 @@
         /* set queued vorbis pages to contain about 1/2 of a second worth of samples */
         source_vorbis->page_samples_trigger = source_vorbis->vi.rate / 2;
         source_vorbis->process_packet = process_vorbis_headers;
+        source_vorbis->initial_audio_page = 1;
     }
     else
     {

Modified: icecast/branches/kh/icecast/src/logging.c
===================================================================
--- icecast/branches/kh/icecast/src/logging.c	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/src/logging.c	2005-11-25 02:54:14 UTC (rev 10429)
@@ -222,6 +222,7 @@
         log_set_filename (errorlog, fn_error);
         log_set_level (errorlog, config->loglevel);
         log_set_trigger (errorlog, config->logsize);
+        log_set_archive_timestamp(errorlog, config->logarchive);
         log_reopen (errorlog);
     }
 
@@ -231,6 +232,7 @@
         snprintf (fn_error, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->access_log);
         log_set_filename (accesslog, fn_error);
         log_set_trigger (accesslog, config->logsize);
+        log_set_archive_timestamp(errorlog, config->logarchive);
         log_reopen (accesslog);
     }
 
@@ -240,6 +242,7 @@
         snprintf (fn_error, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->playlist_log);
         log_set_filename (playlistlog, fn_error);
         log_set_trigger (playlistlog, config->logsize);
+        log_set_archive_timestamp(errorlog, config->logarchive);
         log_reopen (playlistlog);
     }
 }

Modified: icecast/branches/kh/icecast/src/main.c
===================================================================
--- icecast/branches/kh/icecast/src/main.c	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/src/main.c	2005-11-25 02:54:14 UTC (rev 10429)
@@ -196,6 +196,7 @@
         log_to_stderr = 0;
         if (config->logsize)
             log_set_trigger (errorlog, config->logsize);
+        log_set_archive_timestamp(errorlog, config->logarchive);
     } else {
         errorlog = log_open_file(stderr);
         log_to_stderr = 1;
@@ -217,6 +218,7 @@
         log_to_stderr = 0;
         if (config->logsize)
             log_set_trigger (accesslog, config->logsize);
+        log_set_archive_timestamp(errorlog, config->logarchive);
     } else {
         accesslog = log_open_file(stderr);
         log_to_stderr = 1;
@@ -245,6 +247,7 @@
         log_to_stderr = 0;
         if (config->logsize)
             log_set_trigger (playlistlog, config->logsize);
+        log_set_archive_timestamp(errorlog, config->logarchive);
     } else {
         playlistlog = -1;
     }

Modified: icecast/branches/kh/icecast/src/source.c
===================================================================
--- icecast/branches/kh/icecast/src/source.c	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/src/source.c	2005-11-25 02:54:14 UTC (rev 10429)
@@ -1072,19 +1072,8 @@
     /* handle changes in intro file setting */
     if (source->intro_file)
     {
-        int close_it = 0;
-        if (mountinfo)
-        {
-            if (mountinfo->intro_filename && strcmp (mountinfo->intro_filename,
-                        source->intro_filename) != 0)
-                close_it = 1;
-        }
-        else
-            close_it = 1;
         fclose (source->intro_file);
         source->intro_file = NULL;
-        free (source->intro_filename);
-        source->intro_filename = NULL;
     }
     if (mountinfo && mountinfo->intro_filename)
     {
@@ -1094,14 +1083,17 @@
         char *path = malloc (len);
         if (path)
         {
+            FILE *f;
             snprintf (path, len, "%s" PATH_SEPARATOR "%s", config->webroot_dir,
                     mountinfo->intro_filename);
 
-            source->intro_file = fopen (path, "rb");
-            if (source->intro_file == NULL)
+            DEBUG1 ("intro file is %s", mountinfo->intro_filename);
+            f = fopen (path, "rb");
+            if (f)
+                source->intro_file = f;
+            else
                 WARN2 ("Cannot open intro file \"%s\": %s", path, strerror(errno));
             free (path);
-            source->intro_filename = strdup (mountinfo->intro_filename);
         }
     }
 
@@ -1143,8 +1135,6 @@
 
     if (source->fallback_mount)
         DEBUG1 ("fallback %s", source->fallback_mount);
-    if (source->intro_filename)
-        DEBUG1 ("intro file is %s", source->intro_filename);
     if (source->dumpfilename)
         DEBUG1 ("Dumping stream to %s", source->dumpfilename);
     if (mountinfo && mountinfo->on_connect)

Modified: icecast/branches/kh/icecast/src/source.h
===================================================================
--- icecast/branches/kh/icecast/src/source.h	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/src/source.h	2005-11-25 02:54:14 UTC (rev 10429)
@@ -44,7 +44,6 @@
     util_dict *audio_info;
 
     /* name of a file, whose contents are sent at listener connection */
-    char *intro_filename;
     FILE *intro_file;
 
     char *dumpfilename; /* Name of a file to dump incoming stream to */

Modified: icecast/branches/kh/icecast/src/stats.c
===================================================================
--- icecast/branches/kh/icecast/src/stats.c	2005-11-23 22:16:28 UTC (rev 10428)
+++ icecast/branches/kh/icecast/src/stats.c	2005-11-25 02:54:14 UTC (rev 10429)
@@ -53,10 +53,18 @@
 #define STATS_EVENT_REMOVE  4
 #define STATS_EVENT_HIDDEN  5
 
+typedef struct _event_queue_tag
+{
+    volatile stats_event_t *head;
+    volatile stats_event_t **tail;
+} event_queue_t;
+
+#define event_queue_init(qp)    { (qp)->head = NULL; (qp)->tail = &(qp)->head; }
+
 typedef struct _event_listener_tag
 {
-    stats_event_t **queue;
-    mutex_t *mutex;
+    event_queue_t queue;
+    mutex_t mutex;
 
     struct _event_listener_tag *next;
 } event_listener_t;
@@ -68,7 +76,7 @@
 static stats_t _stats;
 static mutex_t _stats_mutex;
 
-static volatile stats_event_t *_global_event_queue;
+static event_queue_t _global_event_queue;
 mutex_t _global_event_mutex;
 
 static volatile event_listener_t *_event_listeners;
@@ -79,10 +87,11 @@
 static int _compare_source_stats(void *a, void *b, void *arg);
 static int _free_stats(void *key);
 static int _free_source_stats(void *key);
-static void _add_event_to_queue(stats_event_t *event, stats_event_t **queue);
+static void _add_event_to_queue(stats_event_t *event, event_queue_t *queue);
 static stats_node_t *_find_node(avl_tree *tree, char *name);
 static stats_source_t *_find_source(avl_tree *tree, char *source);
 static void _free_event(stats_event_t *event);
+static stats_event_t *_get_event_from_queue (event_queue_t *queue);
 
 
 /* simple helper function for creating an event */
@@ -108,19 +117,7 @@
 static void queue_global_event (stats_event_t *event)
 {
     thread_mutex_lock(&_global_event_mutex);
-    if (_global_event_queue == NULL)
-    {
-        _global_event_queue = event;
-    }
-    else
-    {
-        stats_event_t *node = (stats_event_t *)_global_event_queue;
-        while (node->next)
-            node = node->next;
-        node->next = event;
-    }
-    /* DEBUG3("event added (%s, %s, %s)", event->source,
-         event->name, event->value); */
+    _add_event_to_queue (event, &_global_event_queue);
     thread_mutex_unlock(&_global_event_mutex);
 }
 
@@ -136,7 +133,7 @@
     thread_mutex_create("stats", &_stats_mutex);
 
     /* set up stats queues */
-    _global_event_queue = NULL;
+    event_queue_init (&_global_event_queue);
     thread_mutex_create("stats_global_event", &_global_event_mutex);
 
     /* fire off the stats thread */
@@ -147,7 +144,6 @@
 void stats_shutdown()
 {
     int n;
-    stats_event_t *event, *next;
 
     if(!_stats_running) /* We can't shutdown if we're not running. */
         return;
@@ -174,17 +170,17 @@
     avl_tree_free(_stats.source_tree, _free_source_stats);
     avl_tree_free(_stats.global_tree, _free_stats);
 
-    event = (stats_event_t *)_global_event_queue;
-    while(event) {
+    while (1)
+    {
+        stats_event_t *event = _get_event_from_queue (&_global_event_queue);
+        if (event == NULL) break;
         if(event->source)
             free(event->source);
         if(event->value)
             free(event->value);
         if(event->name)
             free(event->name);
-        next = event->next;
         free(event);
-        event = next;
     }
 }
 
@@ -573,11 +569,10 @@
 
     INFO0 ("stats thread started");
     while (_stats_running) {
-        if (_global_event_queue != NULL) {
+        if (_global_event_queue.head != NULL) {
             /* grab the next event from the queue */
             thread_mutex_lock(&_global_event_mutex);
-            event = (stats_event_t *)_global_event_queue;
-            _global_event_queue = event->next;
+            event = _get_event_from_queue (&_global_event_queue);
             thread_mutex_unlock(&_global_event_mutex);
 
             event->next = NULL;
@@ -595,9 +590,9 @@
             listener = (event_listener_t *)_event_listeners;
             while (listener) {
                 copy = _copy_event(event);
-                thread_mutex_lock(listener->mutex);
-                _add_event_to_queue(copy, listener->queue);
-                thread_mutex_unlock(listener->mutex);
+                thread_mutex_lock (&listener->mutex);
+                _add_event_to_queue (copy, &listener->queue);
+                thread_mutex_unlock (&listener->mutex);
 
                 listener = listener->next;
             }
@@ -616,16 +611,15 @@
 }
 
 /* you must have the _stats_mutex locked here */
-static void _unregister_listener(stats_event_t **queue)
+static void _unregister_listener(event_listener_t *listener)
 {
     event_listener_t **prev = (event_listener_t **)&_event_listeners,
                      *current = *prev;
     while (current)
     {
-        if (current->queue == queue)
+        if (current == listener)
         {
             *prev = current->next;
-            free (current);
             break;
         }
         prev = &current->next;
@@ -634,25 +628,6 @@
 }
 
 
-/* you must have the _stats_mutex locked here */
-static void _register_listener(stats_event_t **queue, mutex_t *mutex)
-{
-    event_listener_t *node;
-    event_listener_t *evli = (event_listener_t *)malloc(sizeof(event_listener_t));
-
-    evli->queue = queue;
-    evli->mutex = mutex;
-    evli->next = NULL;
-
-    if (_event_listeners == NULL) {
-        _event_listeners = evli;
-    } else {
-        node = (event_listener_t *)_event_listeners;
-        while (node->next) node = node->next;
-        node->next = evli;
-    }
-}
-
 static stats_event_t *_make_event_from_node(stats_node_t *node, char *source)
 {
     stats_event_t *event = (stats_event_t *)malloc(sizeof(stats_event_t));
@@ -670,35 +645,32 @@
     return event;
 }
 
-static void _add_event_to_queue(stats_event_t *event, stats_event_t **queue)
-{
-    stats_event_t *node;
 
-    if (*queue == NULL) {
-        *queue = event;
-    } else {
-        node = *queue;
-        while (node->next) node = node->next;
-        node->next = event;
-    }
+static void _add_event_to_queue(stats_event_t *event, event_queue_t *queue)
+{
+    *queue->tail = event;
+    queue->tail = (volatile stats_event_t **)&event->next;
 }
 
-static stats_event_t *_get_event_from_queue(stats_event_t **queue)
+
+static stats_event_t *_get_event_from_queue (event_queue_t *queue)
 {
-    stats_event_t *event;
+    stats_event_t *event = NULL;
 
-    if (*queue == NULL) return NULL;
+    if (queue && queue->head)
+    {
+        event = (stats_event_t *)queue->head;
+        queue->head = event->next;
+        if (queue->head == NULL)
+            queue->tail = &queue->head;
+    }
 
-    event = *queue;
-    *queue = (*queue)->next;
-    event->next = NULL;
-
     return event;
 }
 
 static int _send_event_to_client(stats_event_t *event, client_t *client)
 {
-    int ret = -1, len;
+    int len;
     char buf [200];
 
     /* send data to the client!!!! */
@@ -707,12 +679,15 @@
             event->name ? event->name : "null",
             event->value ? event->value : "null");
     if (len > 0 && len < (int)sizeof (buf))
-        ret = client_send_bytes (client, buf, len);
-
-    return (ret == -1) ? 0 : 1;
+    {
+        client_send_bytes (client, buf, len);
+        if (client->con->error)
+            return -1;
+    }
+    return 0;
 }
 
-void _dump_stats_to_queue(stats_event_t **queue)
+void _dump_stats_to_queue (event_queue_t *queue)
 {
     avl_node *node;
     avl_node *node2;
@@ -752,7 +727,7 @@
 ** the queue for all new events atomically.
 ** note: mutex must already be created!
 */
-static void _atomic_get_and_register(stats_event_t **queue, mutex_t *mutex)
+static void _register_listener (event_listener_t *listener)
 {
     avl_node *node;
     avl_node *node2;
@@ -767,7 +742,7 @@
     node = avl_get_first(_stats.global_tree);
     while (node) {
         event = _make_event_from_node((stats_node_t *)node->key, NULL);
-        _add_event_to_queue(event, queue);
+        _add_event_to_queue (event, &listener->queue);
 
         node = avl_get_next(node);
     }
@@ -779,7 +754,7 @@
         node2 = avl_get_first(source->stats_tree);
         while (node2) {
             event = _make_event_from_node((stats_node_t *)node2->key, source->source);
-            _add_event_to_queue(event, queue);
+            _add_event_to_queue (event, &listener->queue);
 
             node2 = avl_get_next(node2);
         }
@@ -788,7 +763,8 @@
     }
 
     /* now we register to receive future event notices */
-    _register_listener(queue, mutex);
+    listener->next = (event_listener_t *)_event_listeners;
+    _event_listeners = listener;
 
     thread_mutex_unlock(&_stats_mutex);
 }
@@ -796,48 +772,44 @@
 void *stats_connection(void *arg)
 {
     client_t *client = (client_t *)arg;
-    stats_event_t *local_event_queue = NULL;
-    mutex_t local_event_mutex;
     stats_event_t *event;
+    event_listener_t listener;
 
     INFO0 ("stats client starting");
 
+    event_queue_init (&listener.queue);
     /* increment the thread count */
     thread_mutex_lock(&_stats_mutex);
     _stats_threads++;
     stats_event_args (NULL, "stats", "%d", _stats_threads);
     thread_mutex_unlock(&_stats_mutex);
 
-    thread_mutex_create("stats local event", &local_event_mutex);
+    thread_mutex_create("stats local event", &listener.mutex);
 
-    _atomic_get_and_register(&local_event_queue, &local_event_mutex);
+    _register_listener (&listener);
 
     while (_stats_running) {
-        thread_mutex_lock(&local_event_mutex);
-        event = _get_event_from_queue(&local_event_queue);
+        thread_mutex_lock (&listener.mutex);
+        event = _get_event_from_queue (&listener.queue);
+        thread_mutex_unlock (&listener.mutex);
         if (event != NULL) {
-            if (!_send_event_to_client(event, client)) {
+            if (_send_event_to_client(event, client) < 0) {
                 _free_event(event);
-                thread_mutex_unlock(&local_event_mutex);
                 break;
             }
             _free_event(event);
-        } else {
-            thread_mutex_unlock(&local_event_mutex);
-            thread_sleep (500000);
             continue;
         }
-                   
-        thread_mutex_unlock(&local_event_mutex);
+        thread_sleep (500000);
     }
 
     thread_mutex_lock(&_stats_mutex);
-    _unregister_listener (&local_event_queue);
+    _unregister_listener (&listener);
     _stats_threads--;
     stats_event_args (NULL, "stats", "%d", _stats_threads);
     thread_mutex_unlock(&_stats_mutex);
 
-    thread_mutex_destroy(&local_event_mutex);
+    thread_mutex_destroy (&listener.mutex);
     client_destroy (client);
     INFO0 ("stats client finished");
 
@@ -918,19 +890,18 @@
 void stats_get_xml(xmlDocPtr *doc, int show_hidden)
 {
     stats_event_t *event;
-    stats_event_t *queue;
+    event_queue_t queue;
     xmlNodePtr node, srcnode;
     source_xml_t *src_nodes = NULL;
     source_xml_t *next;
 
-    queue = NULL;
-    _dump_stats_to_queue(&queue);
+    event_queue_init (&queue);
+    _dump_stats_to_queue (&queue);
 
     *doc = xmlNewDoc("1.0");
     node = xmlNewDocNode(*doc, NULL, "icestats", NULL);
     xmlDocSetRootElement(*doc, node);
 
-
     event = _get_event_from_queue(&queue);
     while (event)
     {
@@ -967,7 +938,6 @@
         }
         avl_tree_unlock (global.source_tree);
     }
-
     while (src_nodes) {
         next = src_nodes->next;
         free(src_nodes->mount);



More information about the commits mailing list