[xiph-cvs] r6646 - in icecast/trunk/icecast: . src

karl at xiph.org karl at xiph.org
Mon May 10 09:17:57 PDT 2004



Author: karl
Date: 2004-05-10 12:17:56 -0400 (Mon, 10 May 2004)
New Revision: 6646

Removed:
   icecast/trunk/icecast/src/geturl.c
   icecast/trunk/icecast/src/geturl.h
Modified:
   icecast/trunk/icecast/configure.in
   icecast/trunk/icecast/src/Makefile.am
   icecast/trunk/icecast/src/admin.c
   icecast/trunk/icecast/src/format_mp3.c
   icecast/trunk/icecast/src/format_vorbis.c
   icecast/trunk/icecast/src/main.c
   icecast/trunk/icecast/src/source.c
   icecast/trunk/icecast/src/source.h
   icecast/trunk/icecast/src/yp.c
   icecast/trunk/icecast/src/yp.h
Log:
Update of the YP code. This should resolve several YP issues that
have been reported, the main one being icecast instability when
there is a YP server outage.

<p><p>Modified: icecast/trunk/icecast/configure.in
===================================================================
--- icecast/trunk/icecast/configure.in	2004-05-09 08:13:35 UTC (rev 6645)
+++ icecast/trunk/icecast/configure.in	2004-05-10 16:17:56 UTC (rev 6646)
@@ -92,7 +92,7 @@
 XIPH_PATH_CURL([
     AC_CHECK_DECL([CURLOPT_NOSIGNAL],
         [ AC_DEFINE([USE_YP], 1, [Define to compile in YP support code])
-        ICECAST_OPTIONAL="$ICECAST_OPTIONAL geturl.o yp.o"
+        ICECAST_OPTIONAL="$ICECAST_OPTIONAL yp.o"
         XIPH_VAR_APPEND([XIPH_CPPFLAGS],[$CURL_CFLAGS])
         XIPH_VAR_PREPEND([XIPH_LIBS],[$CURL_LIBS])
         ], [ AC_MSG_NOTICE([Your curl dev files are too old (7.10 or above required), YP disabled])

Modified: icecast/trunk/icecast/src/Makefile.am
===================================================================
--- icecast/trunk/icecast/src/Makefile.am	2004-05-09 08:13:35 UTC (rev 6645)
+++ icecast/trunk/icecast/src/Makefile.am	2004-05-10 16:17:56 UTC (rev 6646)
@@ -8,11 +8,11 @@
 
 noinst_HEADERS = admin.h cfgfile.h os.h logging.h sighandler.h connection.h global.h\
          util.h slave.h source.h stats.h refbuf.h client.h format.h format_vorbis.h\
-	 compat.h format_mp3.h fserve.h xslt.h geturl.h yp.h event.h auth.h md5.h
+	 compat.h format_mp3.h fserve.h xslt.h yp.h event.h auth.h md5.h
 icecast_SOURCES = cfgfile.c main.c logging.c sighandler.c connection.c global.c\
          util.c slave.c source.c stats.c refbuf.c client.c format.c format_vorbis.c\
          format_mp3.c xslt.c fserve.c event.c admin.c auth.c md5.c
-EXTRA_icecast_SOURCES = geturl.c yp.c
+EXTRA_icecast_SOURCES = yp.c
     
 icecast_DEPENDENCIES = @ICECAST_OPTIONAL@ net/libicenet.la thread/libicethread.la \
     httpp/libicehttpp.la log/libicelog.la avl/libiceavl.la timing/libicetiming.la

Modified: icecast/trunk/icecast/src/admin.c
===================================================================
--- icecast/trunk/icecast/src/admin.c	2004-05-09 08:13:35 UTC (rev 6645)
+++ icecast/trunk/icecast/src/admin.c	2004-05-10 16:17:56 UTC (rev 6646)
@@ -779,10 +779,6 @@
     char *action;
     char *value;
     mp3_state *state;
-#ifdef USE_YP
-    int i;
-    time_t current_time;
-#endif
 
     DEBUG0("Got metadata update request");
 
@@ -813,15 +809,9 @@
         source->mount, value);
     stats_event(source->mount, "title", value);
 
-#ifdef USE_YP
     /* If we get an update on the mountpoint, force a
        yp touch */
-    current_time = time(NULL);
-    for (i=0; i<source->num_yp_directories; i++) {
-        source->ypdata[i]->yp_last_touch = current_time - 
-            source->ypdata[i]->yp_touch_interval + 2;
-    }
-#endif
+    yp_touch (source->mount);
 
     html_success(client, "Metadata update successful");
 }

Modified: icecast/trunk/icecast/src/format_mp3.c
===================================================================
--- icecast/trunk/icecast/src/format_mp3.c	2004-05-09 08:13:35 UTC (rev 6645)
+++ icecast/trunk/icecast/src/format_mp3.c	2004-05-10 16:17:56 UTC (rev 6646)
@@ -357,6 +357,7 @@
                         state->metadata_buffer = NULL;
                         state->metadata_age++;
                         thread_mutex_unlock(&(state->lock));
+                        yp_touch (self->mount);
                     }
 
                     state->offset = 0;

Modified: icecast/trunk/icecast/src/format_vorbis.c
===================================================================
--- icecast/trunk/icecast/src/format_vorbis.c	2004-05-09 08:13:35 UTC (rev 6645)
+++ icecast/trunk/icecast/src/format_vorbis.c	2004-05-10 16:17:56 UTC (rev 6646)
@@ -122,9 +122,6 @@
     refbuf_t *refbuf, *source_refbuf;
     vstate_t *state = (vstate_t *)self->_state;
     source_t *source;
-#ifdef USE_YP
-    time_t current_time;
-#endif
 
     if (data) {
         /* write the data to the buffer */
@@ -199,21 +196,7 @@
                 }
                 thread_mutex_unlock(&source->queue_mutex);
 
-#ifdef USE_YP
-                /* If we get an update on the mountpoint, force a
-                   yp touch */
-
-                if (source) {
-                    /* If we get an update on the mountpoint, force a
-                       yp touch */
-                    current_time = time(NULL);
-                    for (i=0; i<source->num_yp_directories; i++) {
-                        source->ypdata[i]->yp_last_touch = current_time -
-                            source->ypdata[i]->yp_touch_interval + 2;
-                    }
-                }
-#endif
-
+                yp_touch (self->mount);
             }
         }
 

Deleted: icecast/trunk/icecast/src/geturl.c
===================================================================
--- icecast/trunk/icecast/src/geturl.c	2004-05-09 08:13:35 UTC (rev 6645)
+++ icecast/trunk/icecast/src/geturl.c	2004-05-10 16:17:56 UTC (rev 6646)
@@ -1,195 +0,0 @@
-/* Icecast
- *
- * This program is distributed under the GNU General Public License, version 2.
- * A copy of this license is included with this source.
- *
- * Copyright 2000-2004, Jack Moffitt <jack at xiph.org, 
- *                      Michael Smith <msmith at xiph.org>,
- *                      oddsock <oddsock at xiph.org>,
- *                      Karl Heyes <karl at xiph.org>
- *                      and others (see AUTHORS for details).
- */
-
-/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <thread/thread.h>
-
-#include "connection.h"
-#include "refbuf.h"
-#include "client.h"
-#include "logging.h"
-#include "format.h"
-#include "geturl.h"
-#include "source.h"
-#include "cfgfile.h"
-
-#include <curl/curl.h>
-#include <curl/types.h>
-#include <curl/easy.h>
-
-
-#define CATMODULE "geturl" 
-
-static curl_connection curl_connections[NUM_CONNECTIONS];
-static mutex_t _curl_mutex;
-
-size_t curl_write_memory_callback(void *ptr, size_t size, 
-        size_t nmemb, void *data)
-{
-    register int realsize = size * nmemb;
-
-    struct curl_memory_struct *mem = (struct curl_memory_struct *)data;
-
-    if ((realsize + mem->size) < YP_RESPONSE_SIZE-1) {
-        strncat(mem->memory, ptr, realsize);
-    }
-
-    return realsize;
-}
-
-size_t curl_header_memory_callback(void *ptr, size_t size, 
-        size_t nmemb, void *data)
-{
-    char *p1 = 0;
-    char *p2 = 0;
-    int copylen = 0;
-    register int realsize = size * nmemb;
-    struct curl_memory_struct2 *mem = (struct curl_memory_struct2 *)data;
-
-    if (!strncmp(ptr, "SID: ", strlen("SID: "))) {
-        p1 = (char *)ptr + strlen("SID: ");
-        p2 = strchr((const char *)p1, '\r');
-        memset(mem->sid, '\000', sizeof(mem->sid));
-        if (p2) {
-            if (p2-p1 > sizeof(mem->sid)-1) {
-                copylen = sizeof(mem->sid)-1;
-            }
-            else {
-                copylen = p2-p1;
-            }
-            strncpy(mem->sid, p1, copylen);
-        }
-        else {
-            strncpy(mem->sid, p1, sizeof(mem->sid)-1);
-        }
-    }
-    if (!strncmp(ptr, "YPMessage: ", strlen("YPMessage: "))) {
-        p1 = (char *)ptr + strlen("YPMessage: ");
-        p2 = strchr((const char *)p1, '\r');
-        memset(mem->message, '\000', sizeof(mem->message));
-        if (p2) {
-            if (p2-p1 > sizeof(mem->message)-1) {
-                copylen = sizeof(mem->message)-1;
-            }
-            else {
-                copylen = p2-p1;
-            }
-            strncpy(mem->message, p1, copylen);
-        }
-        else {
-            strncpy(mem->message, p1, sizeof(mem->message)-1);
-        }
-    }
-    if (!strncmp(ptr, "TouchFreq: ", strlen("TouchFreq: "))) {
-        p1 = (char *)ptr + strlen("TouchFreq: ");
-        mem->touch_interval = atoi(p1);
-    }
-    if (!strncmp(ptr, "YPResponse: ", strlen("YPResponse: "))) {
-        p1 = (char *)ptr + strlen("YPResponse: ");
-        mem->response = atoi(p1);
-    }
-    return realsize;
-}
-int curl_initialize()
-{
-    int i = 0;
-    thread_mutex_create(&_curl_mutex);
-
-    memset(&curl_connections, 0, sizeof(curl_connections));
-    for (i=0; i<NUM_CONNECTIONS; i++) {
-        curl_connections[i].curl_handle = curl_easy_init();
-        curl_easy_setopt(curl_connections[i].curl_handle, 
-                CURLOPT_WRITEFUNCTION, curl_write_memory_callback);
-        curl_easy_setopt(curl_connections[i].curl_handle, 
-                CURLOPT_WRITEHEADER, 
-                (void *)&(curl_connections[i].header_result));
-        curl_easy_setopt(curl_connections[i].curl_handle, 
-                CURLOPT_HEADERFUNCTION, curl_header_memory_callback);
-        curl_easy_setopt(curl_connections[i].curl_handle, 
-                CURLOPT_FILE, (void *)&(curl_connections[i].result));
-    }
-    return(1);
-}
-void curl_shutdown()
-{
-    int i = 0;
-    for (i=0; i<NUM_CONNECTIONS; i++) {
-        curl_easy_cleanup(curl_connections[i].curl_handle);
-        memset(&(curl_connections[i]), 0, sizeof(curl_connections[i]));
-    }
-    curl_global_cleanup();
-}
-int curl_get_connection()
-{
-    int found = 0;
-    int curl_connection = -1;
-    int i = 0;
-    while (!found) {
-        thread_mutex_lock(&_curl_mutex);
-        for (i=0; i<NUM_CONNECTIONS; i++) {
-            if (!curl_connections[i].in_use) {
-                found = 1;
-                curl_connections[i].in_use = 1;
-                curl_connection = i;
-                break;
-            }
-        }
-        thread_mutex_unlock(&_curl_mutex);
-#ifdef WIN32
-        Sleep(200);
-#else
-        usleep(200);
-#endif
-    }
-    return(curl_connection);
-}
-int curl_release_connection(int which)
-{
-    thread_mutex_lock(&_curl_mutex);
-    curl_connections[which].in_use = 0;
-    memset(&(curl_connections[which].result), 0, 
-                sizeof(curl_connections[which].result));
-    memset(&(curl_connections[which].header_result), 0, 
-                sizeof(curl_connections[which].header_result));
-    thread_mutex_unlock(&_curl_mutex);
-    return 1;
-}
-void curl_print_header_result(struct curl_memory_struct2 *mem) {
-    DEBUG1("SID -> (%s)", mem->sid);
-    DEBUG1("Message -> (%s)", mem->message);
-    DEBUG1("Touch Freq -> (%d)", mem->touch_interval);
-    DEBUG1("Response -> (%d)", mem->response);
-}
-
-
-CURL *curl_get_handle(int which)
-{
-    return curl_connections[which].curl_handle;
-}
-
-struct curl_memory_struct *curl_get_result(int which)
-{
-    return &(curl_connections[which].result);
-}
-
-struct curl_memory_struct2 *curl_get_header_result(int which)
-{
-    return &(curl_connections[which].header_result);
-}

Deleted: icecast/trunk/icecast/src/geturl.h
===================================================================
--- icecast/trunk/icecast/src/geturl.h	2004-05-09 08:13:35 UTC (rev 6645)
+++ icecast/trunk/icecast/src/geturl.h	2004-05-10 16:17:56 UTC (rev 6646)
@@ -1,58 +0,0 @@
-/* Icecast
- *
- * This program is distributed under the GNU General Public License, version 2.
- * A copy of this license is included with this source.
- *
- * Copyright 2000-2004, Jack Moffitt <jack at xiph.org, 
- *                      Michael Smith <msmith at xiph.org>,
- *                      oddsock <oddsock at xiph.org>,
- *                      Karl Heyes <karl at xiph.org>
- *                      and others (see AUTHORS for details).
- */
-
-/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- */
-#ifndef __GETURL_H__
-#define __GETURL_H__
-
-#include <stdio.h>
-
-#include <curl/curl.h>
-#include <curl/types.h>
-#include <curl/easy.h>
-
-#define NUM_CONNECTIONS 10
-#define NAK 0
-#define ACK 1
-#define YP_RESPONSE_SIZE 2046
-#define YP_SID_SIZE 255
-
-struct curl_memory_struct {
-    char memory[YP_RESPONSE_SIZE];
-    size_t size;
-};
-struct curl_memory_struct2 {
-    char sid[YP_SID_SIZE];
-    char message[YP_RESPONSE_SIZE];
-    int touch_interval;
-    int response;
-    size_t size;
-};
-
-typedef struct tag_curl_connection {
-    struct curl_memory_struct result;
-    struct curl_memory_struct2 header_result;
-    CURL *curl_handle;
-    int in_use;
-} curl_connection;
-
-
-int curl_initialize();
-void curl_shutdown();
-CURL *curl_get_handle(int which);
-struct curl_memory_struct *curl_get_result(int which);
-struct curl_memory_struct2 *curl_get_header_result(int which);
-void curl_print_header_result(struct curl_memory_struct2 *mem);
-int curl_get_connection();
-int curl_release_connection(int which);
-
-#endif

Modified: icecast/trunk/icecast/src/main.c
===================================================================
--- icecast/trunk/icecast/src/main.c	2004-05-09 08:13:35 UTC (rev 6645)
+++ icecast/trunk/icecast/src/main.c	2004-05-10 16:17:56 UTC (rev 6646)
@@ -48,10 +48,7 @@
 #include "logging.h"
 #include "xslt.h"
 #include "fserve.h"
-#ifdef USE_YP
-#include "geturl.h"
 #include "yp.h"
-#endif
 
 #include <libxml/xmlmemory.h>
 
@@ -103,9 +100,6 @@
     global_initialize();
     refbuf_initialize();
     xslt_initialize();
-#ifdef USE_YP
-    curl_initialize();
-#endif
 }
 
 static void _shutdown_subsystems(void)
@@ -114,10 +108,8 @@
     xslt_shutdown();
     refbuf_shutdown();
     slave_shutdown();
+    yp_shutdown();
     stats_shutdown();
-#ifdef USE_YP
-    curl_shutdown();
-#endif
 
     /* Now that these are done, we can stop the loggers. */
     _stop_logging();
@@ -478,10 +470,8 @@
     /* let her rip */
     global.running = ICE_RUNNING;
 
-#ifdef USE_YP
     /* Startup yp thread */
     yp_initialize();
-#endif
 
     /* Do this after logging init */
     slave_initialize();

Modified: icecast/trunk/icecast/src/source.c
===================================================================
--- icecast/trunk/icecast/src/source.c	2004-05-09 08:13:35 UTC (rev 6645)
+++ icecast/trunk/icecast/src/source.c	2004-05-10 16:17:56 UTC (rev 6646)
@@ -45,9 +45,6 @@
 #include "logging.h"
 #include "cfgfile.h"
 #include "util.h"
-#ifdef USE_YP
-#include "geturl.h"
-#endif
 #include "source.h"
 #include "format.h"
 #include "auth.h"
@@ -62,7 +59,7 @@
 /* avl tree helper */
 static int _compare_clients(void *compare_arg, void *a, void *b);
 static int _free_client(void *key);
-static int _parse_audio_info(source_t *source, char *s);
+static void _parse_audio_info (source_t *source, const char *s);
 
 /* Allocate a new source with the stated mountpoint, if one already
  * exists with that mountpoint in the global source tree then return
@@ -195,9 +192,6 @@
 void source_clear_source (source_t *source)
 {
     refbuf_t *refbuf;
-#ifdef USE_YP
-    int i;
-#endif
     DEBUG1 ("clearing source \"%s\"", source->mount);
     client_destroy(source->client);
     source->client = NULL;
@@ -233,17 +227,9 @@
         source->format->free_plugin (source->format);
     }
     source->format = NULL;
-#ifdef USE_YP
-    for (i=0; i<source->num_yp_directories; i++)
-    {
-        yp_destroy_ypdata(source->ypdata[i]);
-        source->ypdata[i] = NULL;
-    }
-    source->num_yp_directories = 0;
+    if (source->yp_public)
+        yp_remove (source->mount);
 
-    util_dict_free (source->audio_info);
-    source->audio_info = NULL;
-#endif
     source->queue_size_limit = 0;
     source->listeners = 0;
     source->no_mount = 0;
@@ -380,109 +366,9 @@
 static void source_init (source_t *source)
 {
     ice_config_t *config = config_get_config();
-    char *listenurl;
+    char *listenurl, *str;
     int listen_url_size;
-#ifdef USE_YP
-    char *s;
-    time_t current_time;
-    int    i;
-    char *ai;
 
-    for (i=0;i<config->num_yp_directories;i++) {
-        if (config->yp_url[i]) {
-            source->ypdata[source->num_yp_directories] = yp_create_ypdata();
-            source->ypdata[source->num_yp_directories]->yp_url = 
-                strdup (config->yp_url[i]);
-            source->ypdata[source->num_yp_directories]->yp_url_timeout = 
-                config->yp_url_timeout[i];
-            source->ypdata[source->num_yp_directories]->yp_touch_interval = 0;
-            source->num_yp_directories++;
-        }
-    }
-    
-    source->audio_info = util_dict_new();
-    /* ice-* is icecast, icy-* is shoutcast */
-    if ((s = httpp_getvar(source->parser, "ice-url"))) {
-        add_yp_info(source, "server_url", s, YP_SERVER_URL);
-    }
-    if ((s = httpp_getvar(source->parser, "ice-name"))) {
-        add_yp_info(source, "server_name", s, YP_SERVER_NAME);
-    }
-    if ((s = httpp_getvar(source->parser, "icy-name"))) {
-        add_yp_info(source, "server_name", s, YP_SERVER_NAME);
-    }
-    if ((s = httpp_getvar(source->parser, "ice-url"))) {
-        add_yp_info(source, "server_url", s, YP_SERVER_URL);
-    }
-    if ((s = httpp_getvar(source->parser, "icy-url"))) {
-        add_yp_info(source, "server_url", s, YP_SERVER_URL);
-    }
-    if ((s = httpp_getvar(source->parser, "ice-genre"))) {
-        add_yp_info(source, "genre", s, YP_SERVER_GENRE);
-    }
-    if ((s = httpp_getvar(source->parser, "icy-genre"))) {
-        add_yp_info(source, "genre", s, YP_SERVER_GENRE);
-    }
-    if ((s = httpp_getvar(source->parser, "ice-bitrate"))) {
-        add_yp_info(source, "bitrate", s, YP_BITRATE);
-    }
-    if ((s = httpp_getvar(source->parser, "icy-br"))) {
-        add_yp_info(source, "bitrate", s, YP_BITRATE);
-    }
-    if ((s = httpp_getvar(source->parser, "ice-description"))) {
-        add_yp_info(source, "server_description", s, YP_SERVER_DESC);
-    }
-    if ((s = httpp_getvar(source->parser, "ice-public"))) {
-        stats_event(source->mount, "public", s);
-        source->yp_public = atoi(s);
-    }
-    if ((s = httpp_getvar(source->parser, "icy-pub"))) {
-        stats_event(source->mount, "public", s);
-        source->yp_public = atoi(s);
-    }
-    if ((s = httpp_getvar(source->parser, "ice-audio-info"))) {
-        stats_event(source->mount, "audio_info", s);
-        if (_parse_audio_info(source, s)) {
-            ai = util_dict_urlencode(source->audio_info, '&');
-            add_yp_info(source, "audio_info", 
-                    ai,
-                    YP_AUDIO_INFO);
-            if (ai) {
-                free(ai);
-            }
-        }
-    }
-    for (i=0;i<source->num_yp_directories;i++) {
-        add_yp_info(source, "server_type", 
-                     source->format->format_description,
-                     YP_SERVER_TYPE);
-        if (source->ypdata[i]->listen_url) {
-            free(source->ypdata[i]->listen_url);
-        }
-        /* 6 for max size of port */
-        listen_url_size = strlen("http://") + strlen(config->hostname) +
-            strlen(":") + 6 + strlen (source->mount) + 1;
-        source->ypdata[i]->listen_url = malloc (listen_url_size);
-        sprintf (source->ypdata[i]->listen_url, "http://%s:%d%s",
-                config->hostname, config->port, source->mount);
-    }
-
-    if(source->yp_public) {
-
-        current_time = time(NULL);
-
-        for (i=0;i<source->num_yp_directories;i++) {
-            /* Give the source 5 seconds to update the metadata
-               before we do our first touch */
-            /* Don't permit touch intervals of less than 30 seconds */
-            if (source->ypdata[i]->yp_touch_interval <= 30) {
-                source->ypdata[i]->yp_touch_interval = 30;
-            }
-            source->ypdata[i]->yp_last_touch = 0;
-        }
-    }
-#endif
-
     /* 6 for max size of port */
     listen_url_size = strlen("http://") + strlen(config->hostname) +
         strlen(":") + 6 + strlen(source->mount) + 1;
@@ -494,6 +380,23 @@
     source->burst_on_connect = config->burst_on_connect;
     config_release_config();
 
+    /* maybe better in connection.c */
+    if ((str = httpp_getvar(source->parser, "ice-public")))
+        source->yp_public = atoi(str);
+    if ((str = httpp_getvar(source->parser, "icy-pub")))
+        source->yp_public = atoi(str);
+    if (str == NULL)
+       str = "0";
+    stats_event (source->mount, "public", str);
+
+    str = httpp_getvar(source->parser, "ice-audio-info");
+    source->audio_info = util_dict_new();
+    if (str)
+    {
+        _parse_audio_info (source, str);
+        stats_event (source->mount, "audio_info", str);
+    }
+
     stats_event (source->mount, "listenurl", listenurl);
 
     if (listenurl) {
@@ -546,6 +449,8 @@
 
         avl_tree_unlock(global.source_tree);
     }
+    if (source->yp_public)
+        yp_add (source);
 }
 
 
@@ -858,12 +763,6 @@
     source->running = 0;
     INFO1("Source \"%s\" exiting", source->mount);
 
-#ifdef USE_YP
-    if(source->yp_public) {
-        yp_remove(source);
-    }
-#endif
-    
     /* we have de-activated the source now, so no more clients will be
      * added, now move the listeners we have to the fallback (if any)
      */
@@ -931,35 +830,36 @@
     return 1;
 }
 
-static int _parse_audio_info(source_t *source, char *s)
+static void _parse_audio_info (source_t *source, const char *s)
 {
-    char *token = NULL;
-    char *pvar = NULL;
-    char *variable = NULL;
-    char *value = NULL;
+    const char *start = s;
+    unsigned len;
 
-    while ((token = strtok(s,";")) != NULL) {
-        pvar = strchr(token, '=');
-        if (pvar) {
-            variable = (char *)malloc(pvar-token+1);
-            strncpy(variable, token, pvar-token);    
-            variable[pvar-token] = 0;
-            pvar++;
-            if (strlen(pvar)) {
-                value = util_url_unescape(pvar);
-                util_dict_set(source->audio_info, variable, value);
-                stats_event(source->mount, variable, value);
-                if (value) {
-                    free(value);
-                }
+    while (start != NULL && *start != '\0')
+    {
+        if ((s = strchr (start, ';')) == NULL)
+            len = strlen (start);
+        else
+        {
+            len = (int)(s - start);
+            s++; /* skip passed the ';' */
+        }
+        if (len)
+        {
+            char name[100], value[100];
+            char *esc;
+
+            sscanf (start, "%199[^=]=%199[^;\r\n]", name, value);
+            esc = util_url_unescape (value);
+            if (esc)
+            {
+                util_dict_set (source->audio_info, name, esc);
+                stats_event (source->mount, name, value);
+                free (esc);
             }
-            if (variable) {
-                free(variable);
-            }
         }
-        s = NULL;
+        start = s;
     }
-    return 1;
 }
 
 

Modified: icecast/trunk/icecast/src/source.h
===================================================================
--- icecast/trunk/icecast/src/source.h	2004-05-09 08:13:35 UTC (rev 6645)
+++ icecast/trunk/icecast/src/source.h	2004-05-10 16:17:56 UTC (rev 6646)
@@ -43,7 +43,6 @@
     avl_tree *pending_tree;
 
     rwlock_t *shutdown_rwlock;
-    ypdata_t *ypdata[MAX_YP_DIRECTORIES];
     util_dict *audio_info;
 
     char *dumpfilename; /* Name of a file to dump incoming stream to */

Modified: icecast/trunk/icecast/src/yp.c
===================================================================
--- icecast/trunk/icecast/src/yp.c	2004-05-09 08:13:35 UTC (rev 6645)
+++ icecast/trunk/icecast/src/yp.c	2004-05-10 16:17:56 UTC (rev 6646)
@@ -26,422 +26,660 @@
 #include "client.h"
 #include "logging.h"
 #include "format.h"
-#include "geturl.h"
 #include "source.h"
 #include "cfgfile.h"
 #include "stats.h"
+#include <curl/curl.h>
 
 #define CATMODULE "yp" 
 
-static int    yp_url_timeout [MAX_YP_DIRECTORIES];
+struct yp_server
+{
+    char        *url;
+    unsigned    url_timeout;
+    unsigned    touch_interval;
+    int         remove;
 
+    CURL *curl;
+    struct ypdata_tag *mounts, *pending_mounts;
+    struct yp_server *next;
+    char curl_error[CURL_ERROR_SIZE];
+};
+
+
+
+typedef struct ypdata_tag
+{
+    int remove;
+    int cmd_ok;
+
+    char *sid;
+    char *mount;
+    char *url;
+    char *listen_url;
+    char *server_name;
+    char *server_desc;
+    char *server_genre;
+    char *cluster_password;
+    char *bitrate;
+    char *audio_info;
+    char *server_type;
+    char *current_song;
+
+    struct yp_server *server;
+    time_t      next_update;
+    unsigned    touch_interval;
+    char        *error_msg;
+    unsigned    (*process)(struct ypdata_tag *yp, char *s, unsigned len);
+
+    struct ypdata_tag *next;
+} ypdata_t;
+
+
+static rwlock_t yp_lock;
+static mutex_t yp_pending_lock;
+
+static struct yp_server *active_yps = NULL, *pending_yps = NULL;
+static int yp_update = 0;
+static int yp_running;
+static time_t now;
+static thread_type *yp_thread;
+
+static void *yp_update_thread(void *arg);
+static void add_yp_info (ypdata_t *yp, char *stat_name, void *info, int type);
+static unsigned do_yp_remove (ypdata_t *yp, char *s, unsigned len);
+static unsigned do_yp_add (ypdata_t *yp, char *s, unsigned len);
+static unsigned do_yp_touch (ypdata_t *yp, char *s, unsigned len);
+static void yp_destroy_ypdata(ypdata_t *ypdata);
+
+
+/* curl callback used to parse headers coming back from the YP server */
+static int handle_returned_header (void *ptr, size_t size, size_t nmemb, void *stream)
+{
+    ypdata_t *yp = stream;
+    unsigned bytes = size * nmemb;
+
+    /* DEBUG2 ("header from YP is \"%.*s\"", bytes, ptr); */
+    if (strncmp (ptr, "YPResponse: 1", 13) == 0)
+        yp->cmd_ok = 1;
+
+    if (strncmp (ptr, "YPMessage: ", 11) == 0)
+    {
+        unsigned len = bytes - 11;
+        free (yp->error_msg);
+        yp->error_msg = calloc (1, len);
+        if (yp->error_msg)
+            sscanf (ptr, "YPMessage: %[^\r\n]", yp->error_msg);
+    }
+
+    if (yp->process == do_yp_add)
+    {
+        if (strncmp (ptr, "SID: ", 5) == 0)
+        {
+            unsigned len = bytes - 5;
+            free (yp->sid);
+            yp->sid = calloc (1, len);
+            if (yp->sid)
+                sscanf (ptr, "SID: %[^\r\n]", yp->sid);
+        }
+        if (strncmp (ptr, "TouchFreq: ", 11) == 0)
+        {
+            unsigned secs;
+            sscanf (ptr, "TouchFreq: %u", &secs);
+            if (secs < 30)
+                secs = 30;
+            DEBUG1 ("server touch interval is %u", secs);
+            yp->touch_interval = secs;
+        }
+    }
+    return (int)bytes;
+}
+
+
+/* capture returned data, but don't do anything with it, shouldn't be any */
+static int handle_returned_data (void *ptr, size_t size, size_t nmemb, void *stream)
+{
+    return (int)(size*nmemb);
+}
+
+
+/* search the active and pending YP server lists */
+static struct yp_server *find_yp_server (const char *url)
+{
+    struct yp_server *server;
+
+    server = active_yps;
+    while (server)
+    {
+        if (strcmp (server->url, url) == 0)
+            return server;
+        server = server->next;
+    }
+    server = pending_yps;
+    while (server)
+    {
+        if (strcmp (server->url, url) == 0)
+            break;
+        server = server->next;
+    }
+    return server;
+}
+
+
+static void destroy_yp_server (struct yp_server *server)
+{
+    if (server == NULL)
+        return;
+    DEBUG1 ("Removing YP server entry for %s", server->url);
+    if (server->curl)
+        curl_easy_cleanup (server->curl);
+    if (server->mounts) WARN0 ("active ypdata not freed up");
+    if (server->pending_mounts) WARN0 ("pending ypdata not freed up");
+    free (server->url);
+    free (server);
+}
+
+
+
+/* search for a ypdata entry corresponding to a specific mountpoint */
+static ypdata_t *find_yp_mount (struct yp_server *server, const char *mount)
+{
+    ypdata_t *yp = server->mounts;
+    while (yp)
+    {
+        if (strcmp (yp->mount, mount) == 0)
+            break;
+        yp = yp->next;
+    }
+    return yp;
+}
+
+
 void yp_recheck_config (ice_config_t *config)
 {
-    memcpy (&config->yp_url_timeout[0], yp_url_timeout, (sizeof yp_url_timeout));
+    int i;
+    struct yp_server *server;
+
+    DEBUG0("Updating YP configuration");
+    thread_rwlock_rlock (&yp_lock);
+
+    server = active_yps;
+    while (server)
+    {
+        server->remove = 1;
+        server = server->next;
+    }
+    /* for each yp url in config, check to see if one exists 
+       if not, then add it. */
+    for (i=0 ; i < config->num_yp_directories; i++)
+    {
+        server = find_yp_server (config->yp_url[i]);
+        if (server == NULL)
+        {
+            server = calloc (1, sizeof (struct yp_server));
+
+            if (server == NULL)
+            {
+                destroy_yp_server (server);
+                break;
+            }
+            server->url = strdup (config->yp_url[i]);
+            server->url_timeout = config->yp_url_timeout[i];
+            server->touch_interval = config->touch_interval;
+            server->curl = curl_easy_init();
+            if (server->curl == NULL)
+            {
+                destroy_yp_server (server);
+                break;
+            }
+            if (server->touch_interval < 30)
+                server->touch_interval = 30;
+            curl_easy_setopt (server->curl, CURLOPT_URL, server->url);
+            curl_easy_setopt (server->curl, CURLOPT_HEADERFUNCTION, handle_returned_header);
+            curl_easy_setopt (server->curl, CURLOPT_WRITEFUNCTION, handle_returned_data);
+            curl_easy_setopt (server->curl, CURLOPT_WRITEDATA, server->curl);
+            curl_easy_setopt (server->curl, CURLOPT_TIMEOUT, server->url_timeout);
+            curl_easy_setopt (server->curl, CURLOPT_NOSIGNAL, 1L);
+            curl_easy_setopt (server->curl, CURLOPT_ERRORBUFFER, &(server->curl_error[0]));
+            server->next = pending_yps;
+            pending_yps = server;
+            INFO3 ("Adding new YP server \"%s\" (timeout %ds, default interval %ds)",
+                    server->url, server->url_timeout, server->touch_interval);
+        }
+        else
+        {
+            server->remove = 0;
+        }
+    }
+    thread_rwlock_unlock (&yp_lock);
+    yp_update = 1;
 }
 
+
 void yp_initialize()
 {
     ice_config_t *config = config_get_config();
+    thread_rwlock_create (&yp_lock);
+    thread_mutex_create (&yp_pending_lock);
     yp_recheck_config (config);
     config_release_config ();
-    thread_create("YP Touch Thread", yp_touch_thread,
-                            (void *)NULL, THREAD_DETACHED);
+    yp_thread = thread_create("YP Touch Thread", yp_update_thread,
+                            (void *)NULL, THREAD_ATTACHED);
 }
-static int yp_submit_url(int curl_con, char *yp_url, char *url, char *type, 
-    int timeout)
+
+
+
+/* handler for curl, checks if successful handling occurred */
+static int send_to_yp (const char *cmd, ypdata_t *yp, char *post)
 {
-    int ret = 0;
-    /* If not specified, use a reasonable timeout
-    of 30 seconds */
-    if (timeout == 0) {
-        timeout = 30;
+    int curlcode;
+    struct yp_server *server = yp->server;
+
+    /* DEBUG2 ("send YP (%s):%s", cmd, post); */
+    yp->cmd_ok = 0;
+    curl_easy_setopt (server->curl, CURLOPT_POSTFIELDS, post);
+    curl_easy_setopt (server->curl, CURLOPT_WRITEHEADER, yp);
+    curlcode = curl_easy_perform (server->curl);
+    if (curlcode)
+    {
+        yp->process = do_yp_add;
+        yp->next_update += 60;
+        ERROR2 ("connection to %s failed with \"%s\"", server->url, server->curl_error);
+        return -1;
     }
-    curl_easy_setopt(curl_get_handle(curl_con), CURLOPT_URL, yp_url);
-    curl_easy_setopt(curl_get_handle(curl_con), CURLOPT_POSTFIELDS, url);
-    curl_easy_setopt(curl_get_handle(curl_con), CURLOPT_TIMEOUT, timeout);
-    /* This is to force libcurl to not use signals for timeouts */
-    curl_easy_setopt(curl_get_handle(curl_con), CURLOPT_NOSIGNAL, 1);
-    /* get it! */
-    memset(curl_get_result(curl_con), 0, sizeof(struct curl_memory_struct));
-    memset(curl_get_header_result(curl_con), 0, 
-            sizeof(struct curl_memory_struct2));
+    if (yp->cmd_ok == 0)
+    {
+        yp->process = do_yp_add;
+        yp->next_update += 60;
+        ERROR3 ("YP %s on %s failed: %s", cmd, server->url, yp->error_msg);
+        return -1;
+    }
+    DEBUG2 ("YP %s at %s succeeded", cmd, server->url);
+    return 0;
+}
 
-    curl_easy_perform(curl_get_handle(curl_con));
 
-    curl_print_header_result(curl_get_header_result(curl_con));
+/* routines for building and issues requests to the YP server */
+static unsigned do_yp_remove (ypdata_t *yp, char *s, unsigned len)
+{
+    if (yp->sid)
+    {
+        int ret = snprintf (s, len, "action=remove&sid=%s", yp->sid);
+        if (ret >= (signed)len)
+            return ret+1;
 
-    if (curl_get_header_result(curl_con)->response == ACK) {
-        INFO2("Successfull ACK from %s (%s)", type, yp_url);
-        ret = 1;
+        INFO1 ("clearing up YP entry for %s", yp->mount);
+        send_to_yp ("remove", yp, s);
+        yp->remove = 1;
+        free (yp->sid);
+        yp->sid = NULL;
+        yp->process = do_yp_add;
+        yp_update = 1;
     }
-    else {
-        if (strlen(curl_get_header_result(curl_con)->message) > 0) {
-            ERROR3("Got a NAK from %s(%s) (%s)", type,
-                    curl_get_header_result(curl_con)->message, yp_url);
+    return 0;
+}
+
+
+static unsigned do_yp_add (ypdata_t *yp, char *s, unsigned len)
+{
+    int ret = snprintf (s, len, "action=add&sn=%s&genre=%s&cpswd=%s&desc="
+                    "%s&url=%s&listenurl=%s&type=%s&b=%s&%s\r\n",
+                    yp->server_name, yp->server_genre, yp->cluster_password,
+                    yp->server_desc, yp->url, yp->listen_url,
+                    yp->server_type, yp->bitrate, yp->audio_info);
+    if (ret >= (signed)len)
+        return ret+1;
+    if (send_to_yp ("add", yp, s) == 0)
+    {
+        yp->process = do_yp_touch;
+        /* force first touch in 5 secs */
+        yp->next_update = time(NULL) + 5;
+    }
+
+    return 0;
+}
+
+
+static unsigned do_yp_touch (ypdata_t *yp, char *s, unsigned len)
+{
+    unsigned listeners = 0;
+    char *val, *artist, *title;
+    int ret;
+
+    artist = (char *)stats_get_value (yp->mount, "artist");
+    title = (char *)stats_get_value (yp->mount, "title");
+    if (artist || title)
+    {
+         char *song;
+         char *separator = " - ";
+         if (artist == NULL)
+         {
+             artist = strdup("");
+             separator = "";
+         }
+         if (title == NULL) title = strdup("");
+         song = malloc (strlen (artist) + strlen (title) + strlen (separator) +1);
+         if (song)
+         {
+             sprintf (song, "%s%s%s", artist, separator, title);
+             add_yp_info(yp, "yp_currently_playing", song, YP_CURRENT_SONG);
+             free (song);
+         }
+    }
+    free (artist);
+    free (title);
+
+    val = (char *)stats_get_value (yp->mount, "listeners");
+    if (val)
+    {
+        listeners = atoi (val);
+        free (val);
+    }
+    ret = snprintf (s, len, "action=touch&sid=%s&st=%s&listeners=%u\r\n", 
+            yp->sid, yp->current_song, listeners);
+
+    if (ret >= (signed)len)
+        return ret+1; /* space required for above text and nul*/
+
+    send_to_yp ("touch", yp, s);
+    return 0;
+}
+
+
+
+static void process_ypdata (struct yp_server *server, ypdata_t *yp)
+{
+    unsigned len = 512;
+    char *s = NULL, *tmp;
+
+    if (now < yp->next_update)
+        return;
+    yp->next_update = now + yp->touch_interval;
+
+    /* loop just in case the memory area isn't big enough */
+    while (1)
+    {
+        unsigned ret;
+        if ((tmp = realloc (s, len)) == NULL)
+            return;
+        s = tmp;
+
+        ret = yp->process (yp, s, len);
+        if (ret == 0)
+        {
+           free (s);
+           return;
         }
-        else {
-            ERROR2("Got a NAK from %s(Unknown) (%s)", type, yp_url);
-        }
-        ret = 0;
+        len = ret;
     }
-    return ret;
 }
 
-void *yp_touch_thread(void *arg)
+
+static void yp_process_server (struct yp_server *server)
 {
-    yp_touch();
-    return NULL;
+    ypdata_t *yp;
+
+    /* DEBUG1("processing yp server %s", server->url); */
+    yp = server->mounts;
+    while (yp)
+    {
+        now = time (NULL);
+        process_ypdata (server, yp);
+        yp = yp->next;
+    }
 }
 
-int yp_remove(source_t *source)
+
+
+static ypdata_t *create_yp_entry (source_t *source)
 {
-    char *url = NULL;
-    int url_size = 0;
-    int ret = 0;
-    int curl_con = 0;
-    int i = 0;
+    ypdata_t *yp;
+    char *s;
 
-    time_t current_time = 0;
+    if (source->running == 0 || source->yp_public == 0)
+        return NULL;
+    yp = calloc (1, sizeof (ypdata_t));
+    do
+    {
+        unsigned len = 512;
+        int ret;
+        char *url;
+        ice_config_t *config;
 
-    current_time = time(NULL);
+        if (yp == NULL)
+            break;
+        yp->mount = strdup (source->mount);
+        yp->server_name = strdup ("");
+        yp->server_desc = strdup ("");
+        yp->server_genre = strdup ("");
+        yp->bitrate = strdup ("");
+        yp->server_desc = strdup ("");
+        yp->server_type = strdup ("");
+        yp->cluster_password = strdup ("");
+        yp->url = strdup ("");
+        yp->current_song = strdup ("");
+        yp->audio_info = strdup ("");
+        yp->process = do_yp_add;
 
-    for (i=0; i<source->num_yp_directories; i++) {
-        source->ypdata[i]->yp_last_touch = current_time;
-        if (source->ypdata[i]->sid == 0) {
-            return 0;
+        url = malloc (len);
+        if (url == NULL)
+            break;
+        config = config_get_config();
+        ret = snprintf (url, len, "http://%s:%d%s", config->hostname, config->port, source->mount);
+        if (ret >= (signed)len)
+        {
+            s = realloc (url, ++ret);
+            if (s) url = s;
+            snprintf (url, ret, "http://%s:%d%s", config->hostname, config->port, source->mount);
         }
-        else {
-            if (strlen(source->ypdata[i]->sid) == 0) {
-                return 0;
-            }
+        config_release_config();
+        yp->listen_url = util_url_escape (url);
+        free (url);
+        if (yp->listen_url == NULL)
+            break;
+
+        /* ice-* is icecast, icy-* is shoutcast */
+        add_yp_info (yp, "server_type", source->format->format_description, YP_SERVER_TYPE);
+        if ((s = httpp_getvar(source->parser, "ice-name"))) {
+            add_yp_info (yp, "server_name", s, YP_SERVER_NAME);
         }
-        if (source->ypdata) {
-            url_size = strlen("action=remove&sid=") + 1;
-            url_size += strlen(source->ypdata[i]->sid);
-            url_size += 1024;
-            url = malloc(url_size);
-            sprintf(url, "action=remove&sid=%s", 
-                    source->ypdata[i]->sid);
-            curl_con = curl_get_connection();
-            if (curl_con < 0) {
-                ERROR0("Unable to get auth connection");
-            }
-            else {
-                /* specify URL to get */
-                ret = yp_submit_url(curl_con, source->ypdata[i]->yp_url, 
-                        url, "yp_remove", yp_url_timeout[i]);
-            }
-            if (url) {
-                free(url);
-            }
-            curl_release_connection(curl_con);
+        if ((s = httpp_getvar(source->parser, "icy-name"))) {
+            add_yp_info (yp, "server_name", s, YP_SERVER_NAME);
         }
-    }
-    return 1;
+        if ((s = httpp_getvar(source->parser, "ice-url"))) {
+            add_yp_info(yp, "server_url", s, YP_SERVER_URL);
+        }
+        if ((s = httpp_getvar(source->parser, "icy-url"))) {
+            add_yp_info(yp, "server_url", s, YP_SERVER_URL);
+        }
+        if ((s = httpp_getvar(source->parser, "ice-genre"))) {
+            add_yp_info(yp, "genre", s, YP_SERVER_GENRE);
+        }
+        if ((s = httpp_getvar(source->parser, "icy-genre"))) {
+            add_yp_info(yp, "genre", s, YP_SERVER_GENRE);
+        }
+        if ((s = httpp_getvar(source->parser, "ice-bitrate"))) {
+            add_yp_info(yp, "bitrate", s, YP_BITRATE);
+        }
+        if ((s = httpp_getvar(source->parser, "icy-br"))) {
+            add_yp_info(yp, "bitrate", s, YP_BITRATE);
+        }
+        if ((s = httpp_getvar(source->parser, "ice-description"))) {
+            add_yp_info(yp, "server_description", s, YP_SERVER_DESC);
+        }
+        s = util_dict_urlencode (source->audio_info, '&');
+        if (s)
+            add_yp_info (yp, "audio_info", s, YP_AUDIO_INFO);
+        free(s);
+        return yp;
+    } while (0);
+
+    yp_destroy_ypdata (yp);
+    return NULL;
 }
-int yp_touch()
+
+
+/* Check for changes in the YP servers configured */
+static void check_servers ()
 {
-    char *url = NULL;
-    int url_size = 0;
-    int ret = 0;
-    int curl_con = 0;
-    int i = 0;
-    int regen_sid = 0;
-    time_t  current_time = 0;
-    avl_node *node;
-    source_t *source;
-    char current_song[256];
-    char tyme[128];
-    char *s;
+    struct yp_server *server = active_yps, **server_p = &active_yps;
 
-    while (global.running == ICE_RUNNING) {
-    avl_tree_rlock(global.source_tree);
-    node = avl_get_first(global.source_tree);
-    while (node) {
-        source = (source_t *)node->key;
-        if (source->running == 0)
+    while (server)
+    {
+        if (server->remove)
         {
-            node = avl_get_next (node);
+            struct yp_server *to_go = server;
+            DEBUG1 ("YP server \"%s\"removed", server->url);
+            *server_p = server->next;
+            server = server->next;
+            destroy_yp_server (to_go);
             continue;
         }
-        current_time = time(NULL);
-        if (!source->yp_public) {
-            node = avl_get_next(node);
-            continue;
-        }
-        for (i=0; i<source->num_yp_directories; i++) {
-            if (current_time > (source->ypdata[i]->yp_last_touch +
-                        source->ypdata[i]->yp_touch_interval)) {
-                current_song[0] = 0;
-                regen_sid = 0;
-                if ((s = (char *)stats_get_value(source->mount, "artist"))) {
-                    strncat(current_song, s,
-                            sizeof(current_song) - 1);
-                    if (strlen(current_song) + 4 <
-                            sizeof(current_song))
-                    {
-                        strncat(current_song, " - ", 3);
-                    }
-                    if (s) {
-                        free(s);
-                    }
-                }
-                if ((s = (char *)stats_get_value(source->mount, "title"))) {
-                    if (strlen(current_song) + strlen(s)
-                            < sizeof(current_song) -1)
-                    {
-                        strncat(current_song,
-                                s,
-                                sizeof(current_song) - 1 -
-                                strlen(current_song));
-                    }
-                    if (s) {
-                        free(s);
-                    }
-                }
-                add_yp_info(source, "current_song", current_song, 
-                    YP_CURRENT_SONG);
+        server_p = &server->next;
+        server = server->next;
+    }
+    /* add new server entries */
+    while (pending_yps)
+    {
+        avl_node *node;
 
-                source->ypdata[i]->yp_last_touch = current_time;
-                if (source->ypdata[i]->sid == 0) {
-                    regen_sid = 1;
-                }
-                else {
-                    if (strlen(source->ypdata[i]->sid) == 0) {
-                        regen_sid = 1;
-                    }
-                }
-                if (regen_sid) {
-                    yp_add(source, i);
-                }
-                if (source->ypdata[i]->sid != 0) {
-                    if (strlen(source->ypdata[i]->sid) != 0) {
-                        if (source->ypdata) {
-                            struct tm tm;
-                            url_size = 
-                                strlen("action=touch&sid=&st=&listeners=") + 1;
-                            if (source->ypdata[i]->current_song) {
-                                url_size += 
-                                strlen(source->ypdata[i]->current_song);
-                            }
-                            else {
-                                source->ypdata[i]->current_song = 
-                                    (char *)malloc(1);
-                                source->ypdata[i]->current_song[0] = 0;
-                            }
-                            if (source->ypdata[i]->sid) {
-                                url_size += strlen(source->ypdata[i]->sid);
-                            }
-                            else {
-                                source->ypdata[i]->sid = (char *)malloc(1);
-                                source->ypdata[i]->sid[0] = 0;
-                            }
-                            url_size += 1024;
-                            url = malloc(url_size);
-                            sprintf(url, 
-                                "action=touch&sid=%s&st=%s&listeners=%ld", 
-                                source->ypdata[i]->sid,
-                                source->ypdata[i]->current_song,
-                                source->listeners);
-            
-                            curl_con = curl_get_connection();
-                            if (curl_con < 0) {
-                                ERROR0("Unable to get auth connection");
-                            }
-                            else {
-                                /* specify URL to get */
-                                ret = yp_submit_url(curl_con, 
-                                    source->ypdata[i]->yp_url, 
-                                    url, "yp_touch", yp_url_timeout[i]);
-                                if (!ret) {
-                                    source->ypdata[i]->sid[0] = 0;
-                                }
-                            }
-                            if (url) {
-                               free(url);
-                            } 
-                            curl_release_connection(curl_con);
-                            memset(tyme, '\000', sizeof(tyme));
-                            localtime_r (&current_time, &tm);
-                            strftime(tyme, 128, "%Y-%m-%d  %H:%M:%S", &tm); 
-                            stats_event(source->mount, "yp_last_touch", tyme);
-                            source->ypdata[i]->yp_last_touch = current_time;
-                        }
-                    }
-                }
+        server = pending_yps;
+        pending_yps = server->next;
+
+        DEBUG1("Add pending yps %s", server->url);
+        server->next = active_yps;
+        active_yps = server;
+
+        /* new YP server configured, need to populate with existing sources */
+        avl_tree_rlock (global.source_tree);
+        node = avl_get_first (global.source_tree);
+        while (node)
+        {
+            ypdata_t *yp;
+
+            source_t *source = node->key;
+            if ((yp = create_yp_entry (source)) != NULL)
+            {
+                DEBUG1 ("Adding existing mount %s", source->mount);
+                yp->server = server;
+                yp->touch_interval = server->touch_interval;
+                yp->next = server->mounts;
+                server->mounts = yp;
             }
+            node = avl_get_next (node);
         }
-        node = avl_get_next(node);
+        avl_tree_unlock (global.source_tree);
     }
-    avl_tree_unlock(global.source_tree);
-    thread_sleep(200000);
+}
+
+
+static void add_pending_yp (struct yp_server *server)
+{
+    ypdata_t *current, *yp;
+    unsigned count = 0;
+
+    if (server->pending_mounts == NULL)
+        return;
+    current = server->mounts;
+    server->mounts = server->pending_mounts;
+    server->pending_mounts = NULL;
+    yp = server->mounts;
+    while (1)
+    {
+        count++;
+        if (yp->next == NULL)
+            break;
+        yp = yp->next;
     }
+    yp->next = current;
+    DEBUG2 ("%u YP entries added to %s", count, server->url);
+}
 
 
-    return 1;
-}
-int yp_add(source_t *source, int which)
+static void delete_marked_yp (struct yp_server *server)
 {
-    char *url = NULL;
-    int url_size = 0;
-    int ret = 0;
-    int curl_con = 0;
-    int i = 0;
-    int ok = 0;
+    ypdata_t *yp = server->mounts, **prev = &server->mounts;
 
-    for (i=0; i<source->num_yp_directories; i++) {
-        if (which != -1) {
-            if (i == which) {
-                ok = 1;
-            }
-            else {
-                ok = 0;
-            }
+    while (yp)
+    {
+        if (yp->remove)
+        {
+            ypdata_t *to_go = yp;
+            DEBUG2 ("removed %s from YP server %s", yp->mount, server->url);
+            *prev = yp->next;
+            yp = yp->next;
+            yp_destroy_ypdata (to_go);
+            continue;
         }
-        else {
-            ok = 1;
-        }
+        prev = &yp->next;
+        yp = yp->next;
+    }
+}
 
-        if (ok) {
-            if (source->ypdata[i]) {
-                url_size = strlen("action=add&sn=&genre=&cpswd="
-                                  "&desc=&url=&listenurl=&type=&b=&")
-                                  + 1;
-                if (source->ypdata[i]->server_name) {
-                    url_size += strlen(source->ypdata[i]->server_name);
-                }
-                else {
-                    source->ypdata[i]->server_name = (char *)malloc(1);
-                    source->ypdata[i]->server_name[0] = 0;
-                }
-                if (source->ypdata[i]->server_desc) {
-                    url_size += strlen(source->ypdata[i]->server_desc);
-                }
-                else {
-                    source->ypdata[i]->server_desc = (char *)malloc(1);
-                    source->ypdata[i]->server_desc[0] = 0;
-                }
-                if (source->ypdata[i]->server_genre) {
-                    url_size += strlen(source->ypdata[i]->server_genre);
-                }
-                else {
-                    source->ypdata[i]->server_genre = (char *)malloc(1);
-                    source->ypdata[i]->server_genre[0] = 0;
-                }
-                if (source->ypdata[i]->cluster_password) {
-                    url_size += strlen(source->ypdata[i]->cluster_password);
-                }
-                else {
-                    source->ypdata[i]->cluster_password = (char *)malloc(1);
-                    source->ypdata[i]->cluster_password[0] = 0;
-                }
-                if (source->ypdata[i]->server_url) {
-                    url_size += strlen(source->ypdata[i]->server_url);
-                }
-                else {
-                    source->ypdata[i]->server_url = (char *)malloc(1);
-                    source->ypdata[i]->server_url[0] = 0;
-                }
-                if (source->ypdata[i]->listen_url) {
-                    url_size += strlen(source->ypdata[i]->listen_url);
-                }
-                else {
-                    source->ypdata[i]->listen_url = (char *)malloc(1);
-                    source->ypdata[i]->listen_url[0] = 0;
-                }
-                if (source->ypdata[i]->server_type) {
-                    url_size += strlen(source->ypdata[i]->server_type);
-                }
-                else {
-                    source->ypdata[i]->server_type = (char *)malloc(1);
-                    source->ypdata[i]->server_type[0] = 0;
-                }
-                if (source->ypdata[i]->bitrate) {
-                    url_size += strlen(source->ypdata[i]->bitrate);
-                }
-                else {
-                    source->ypdata[i]->bitrate = (char *)malloc(1);
-                    source->ypdata[i]->bitrate[0] = 0;
-                }
-                if (source->ypdata[i]->current_song) {
-                    url_size += strlen(source->ypdata[i]->current_song);
-                }
-                else {
-                    source->ypdata[i]->current_song = (char *)malloc(1);
-                    source->ypdata[i]->current_song[0] = 0;
-                }
-                if (source->ypdata[i]->audio_info) {
-                    url_size += strlen(source->ypdata[i]->audio_info);
-                }
-                else {
-                    source->ypdata[i]->audio_info = (char *)malloc(1);
-                    source->ypdata[i]->audio_info[0] = 0;
-                }
 
-                url_size += 1024;
-                url = malloc(url_size);
-                sprintf(url, "action=add&sn=%s&genre=%s&cpswd=%s&desc="
-                             "%s&url=%s&listenurl=%s&type=%s&b=%s&%s", 
-                        source->ypdata[i]->server_name,
-                        source->ypdata[i]->server_genre,
-                        source->ypdata[i]->cluster_password,
-                        source->ypdata[i]->server_desc,
-                        source->ypdata[i]->server_url,
-                        source->ypdata[i]->listen_url,
-                        source->ypdata[i]->server_type,
-                        source->ypdata[i]->bitrate,
-                        source->ypdata[i]->audio_info);
+static void *yp_update_thread(void *arg)
+{
+    INFO0("YP update thread started");
 
-               curl_con = curl_get_connection();
-               if (curl_con < 0) {
-                   ERROR0("Unable to get auth connection");
-               }
-               else {
-                   /* specify URL to get */
-                   ret = yp_submit_url(curl_con, source->ypdata[i]->yp_url, 
-                           url, "yp_add", yp_url_timeout[i]);
+    yp_running = 1;
+    while (yp_running)
+    {
+        struct yp_server *server;
 
-                   if (ret) {
-                       if (strlen(curl_get_header_result(curl_con)->sid) > 0) {
-                           if (source->ypdata) {
-                               if (source->ypdata[i]->sid) {
-                                   free(source->ypdata[i]->sid);
-                                   source->ypdata[i]->sid = NULL;
-                               }
-                               source->ypdata[i]->sid = (char *)malloc(
-                                      strlen(curl_get_header_result(curl_con)->
-                                           sid) +1);
-                               strcpy(source->ypdata[i]->sid, 
-                                       curl_get_header_result(curl_con)->sid);
-                               source->ypdata[i]->yp_touch_interval = 
-                                   curl_get_header_result(
-                                           curl_con)->touch_interval;
-                           }
-                       }
-                   }
-               }
-               if (url) {
-                   free(url);
-               }
-               curl_release_connection(curl_con);
+        thread_sleep (200000);
+
+        /* do the YP communication */
+        thread_rwlock_rlock (&yp_lock);
+        server = active_yps;
+        while (server)
+        {
+            /* DEBUG1 ("trying %s", server->url); */
+            yp_process_server (server);
+            server = server->next;
+        }
+        thread_rwlock_unlock (&yp_lock);
+
+        /* update the local YP structure */
+        if (yp_update)
+        {
+            thread_rwlock_wlock (&yp_lock);
+            check_servers ();
+            server = active_yps;
+            while (server)
+            {
+                /* DEBUG1 ("Checking yps %s", server->url); */
+                add_pending_yp (server);
+                delete_marked_yp (server);
+                server = server->next;
             }
+            yp_update = 0;
+            thread_rwlock_unlock (&yp_lock);
         }
     }
-    return 1;
-}
+    thread_rwlock_destroy (&yp_lock);
+    thread_mutex_destroy (&yp_pending_lock);
+    /* free server and ypdata left */
+    while (active_yps)
+    {
+        struct yp_server *server = active_yps;
+        active_yps = server->next;
+        destroy_yp_server (server);
+    }
 
-ypdata_t *yp_create_ypdata()
-{
-    return calloc(1, sizeof(ypdata_t));
+    return NULL;
 }
 
-void yp_destroy_ypdata(ypdata_t *ypdata)
+
+
+static void yp_destroy_ypdata(ypdata_t *ypdata)
 {
     if (ypdata) {
-        if (ypdata->yp_url) {
-            free(ypdata->yp_url);
+        if (ypdata->mount) {
+            free (ypdata->mount);
         }
+        if (ypdata->url) {
+            free (ypdata->url);
+        }
         if (ypdata->sid) {
             free(ypdata->sid);
         }
@@ -457,9 +695,6 @@
         if (ypdata->cluster_password) {
             free(ypdata->cluster_password);
         }
-        if (ypdata->server_url) {
-            free(ypdata->server_url);
-        }
         if (ypdata->listen_url) {
             free(ypdata->listen_url);
         }
@@ -475,119 +710,181 @@
         if (ypdata->audio_info) {
             free(ypdata->audio_info);
         }
-        free(ypdata);
+        free (ypdata->error_msg);
+        free (ypdata);
     }
 }
 
-void add_yp_info(source_t *source, char *stat_name, 
-            void *info, int type)
+static void add_yp_info (ypdata_t *yp, char *stat_name, void *info, int type)
 {
     char *escaped;
-    int i;
-    if (!info) {
+
+    if (!info)
         return;
-    }
-    for (i=0;i<source->num_yp_directories;i++) {
-        switch (type) {
+
+    switch (type)
+    {
         case YP_SERVER_NAME:
-                escaped = util_url_escape(info);
-                if (escaped) {
-                    if (source->ypdata[i]->server_name) {
-                        free(source->ypdata[i]->server_name);
-                    }
-                    source->ypdata[i]->server_name = 
-                         malloc(strlen((char *)escaped) +1);
-                    strcpy(source->ypdata[i]->server_name, (char *)escaped);
-                    stats_event(source->mount, stat_name, (char *)info);
-                    free(escaped);
-                }
-                break;
+            escaped = util_url_escape(info);
+            if (escaped)
+            {
+                if (yp->server_name)
+                    free (yp->server_name);
+                yp->server_name = escaped;
+                stats_event (yp->mount, stat_name, (char *)info);
+            }
+            break;
         case YP_SERVER_DESC:
-                escaped = util_url_escape(info);
-                if (escaped) {
-                    if (source->ypdata[i]->server_desc) {
-                        free(source->ypdata[i]->server_desc);
-                    }
-                    source->ypdata[i]->server_desc = 
-                        malloc(strlen((char *)escaped) +1);
-                    strcpy(source->ypdata[i]->server_desc, (char *)escaped);
-                    stats_event(source->mount, stat_name, (char *)info);
-                    free(escaped);
-                }
-                break;
+            escaped = util_url_escape(info);
+            if (escaped)
+            {
+                if (yp->server_desc)
+                    free (yp->server_desc);
+                yp->server_desc = escaped;
+                stats_event(yp->mount, stat_name, (char *)info);
+            }
+            break;
         case YP_SERVER_GENRE:
-                escaped = util_url_escape(info);
-                if (escaped) {
-                    if (source->ypdata[i]->server_genre) {
-                        free(source->ypdata[i]->server_genre);
-                    }
-                    source->ypdata[i]->server_genre = 
-                        malloc(strlen((char *)escaped) +1);
-                    strcpy(source->ypdata[i]->server_genre, (char *)escaped);
-                    stats_event(source->mount, stat_name, (char *)info);
-                    free(escaped);
-                }
-                break;
+            escaped = util_url_escape(info);
+            if (escaped)
+            {
+                if (yp->server_genre)
+                    free (yp->server_genre);
+                yp->server_genre = escaped;
+                stats_event (yp->mount, stat_name, (char *)info);
+            }
+            break;
         case YP_SERVER_URL:
-                escaped = util_url_escape(info);
-                if (escaped) {
-                    if (source->ypdata[i]->server_url) {
-                        free(source->ypdata[i]->server_url);
-                    }
-                    source->ypdata[i]->server_url = 
-                        malloc(strlen((char *)escaped) +1);
-                    strcpy(source->ypdata[i]->server_url, (char *)escaped);
-                    stats_event(source->mount, stat_name, (char *)info);
-                    free(escaped);
-                }
-                break;
+            escaped = util_url_escape(info);
+            if (escaped)
+            {
+                if (yp->url)
+                    free (yp->url);
+                yp->url = escaped;
+                stats_event (yp->mount, stat_name, (char *)info);
+            }
+            break;
         case YP_BITRATE:
-                escaped = util_url_escape(info);
-                if (escaped) {
-                    if (source->ypdata[i]->bitrate) {
-                        free(source->ypdata[i]->bitrate);
-                    }
-                    source->ypdata[i]->bitrate = 
-                        malloc(strlen((char *)escaped) +1);
-                    strcpy(source->ypdata[i]->bitrate, (char *)escaped);
-                    stats_event(source->mount, stat_name, (char *)info);
-                    free(escaped);
-                }
-                break;
+            escaped = util_url_escape(info);
+            if (escaped)
+            {
+                if (yp->bitrate)
+                    free (yp->bitrate);
+                yp->bitrate = escaped;
+                stats_event (yp->mount, stat_name, (char *)info);
+            }
+            break;
         case YP_AUDIO_INFO:
-                if (source->ypdata[i]->audio_info) {
-                    free(source->ypdata[i]->audio_info);
-                }
-                source->ypdata[i]->audio_info = 
-                    malloc(strlen((char *)info) +1);
-                strcpy(source->ypdata[i]->audio_info, (char *)info);
-                break;
+            if (yp->audio_info)
+                free (yp->audio_info);
+            yp->audio_info = strdup (info);
+            break;
         case YP_SERVER_TYPE:
-                escaped = util_url_escape(info);
-                if (escaped) {
-                    if (source->ypdata[i]->server_type) {
-                        free(source->ypdata[i]->server_type);
-                    }
-                    source->ypdata[i]->server_type = 
-                        malloc(strlen((char *)escaped) +1);
-                    strcpy(source->ypdata[i]->server_type, (char *)escaped);
-                    free(escaped);
-                }
-                break;
+            escaped = util_url_escape(info);
+            if (escaped)
+            {
+                if (yp->server_type)
+                    free (yp->server_type);
+                yp->server_type = escaped;
+            }
+            break;
         case YP_CURRENT_SONG:
-                escaped = util_url_escape(info);
-                if (escaped) {
-                    if (source->ypdata[i]->current_song) {
-                        free(source->ypdata[i]->current_song);
-                    }
-                    source->ypdata[i]->current_song = 
-                        malloc(strlen((char *)escaped) +1);
-                    strcpy(source->ypdata[i]->current_song, (char *)escaped);
-                    stats_event(source->mount, "yp_currently_playing", 
-                        (char *)info);
-                    free(escaped);
-                }
-                break;
+            escaped = util_url_escape(info);
+            if (escaped)
+            {
+                if (yp->current_song)
+                    free (yp->current_song);
+                yp->current_song = escaped;
+                stats_event (yp->mount, "yp_currently_playing", (char *)info);
+            }
+            break;
+    }
+}
+
+
+/* Add YP entries to active servers */
+void yp_add (source_t *source)
+{
+    struct yp_server *server;
+
+    /* make sure YP thread is not modifying the lists */
+    thread_rwlock_rlock (&yp_lock);
+
+    /* make sure we don't race against another yp_add */
+    thread_mutex_lock (&yp_pending_lock);
+    server = active_yps;
+    while (server)
+    {
+        ypdata_t *yp;
+        /* add new ypdata to each servers pending yp */
+        if ((yp = create_yp_entry (source)) != NULL)
+        {
+            DEBUG2 ("Adding %s to %s", source->mount, server->url);
+            yp->server = server;
+            yp->touch_interval = server->touch_interval;
+            yp->next = server->pending_mounts;
+            server->pending_mounts = yp;
+            yp_update = 1;
         }
+        server = server->next;
     }
+    thread_mutex_unlock (&yp_pending_lock);
+    thread_rwlock_unlock (&yp_lock);
+    /* DEBUG1 ("Added %s to YP ", source->mount); */
 }
+
+
+
+/* Mark an existing entry in the YP list as to be marked for deletion */
+void yp_remove (const char *mount)
+{
+    struct yp_server *server = active_yps;
+
+    thread_rwlock_rlock (&yp_lock);
+    while (server)
+    {
+        ypdata_t *yp = find_yp_mount (server, mount);
+        if (yp)
+        {
+            yp->process = do_yp_remove;
+            yp->next_update = 0;
+        }
+        server = server->next;
+    }
+    thread_rwlock_unlock (&yp_lock);
+}
+
+
+/* This is similar to yp_remove, but we force a touch
+ * attempt */
+void yp_touch (const char *mount)
+{
+    struct yp_server *server = active_yps;
+    time_t trigger;
+
+    thread_rwlock_rlock (&yp_lock);
+    /* do update in 3 secs, give stats chance to update */
+    trigger = time(NULL) + 3;
+    while (server)
+    {
+        ypdata_t *yp = find_yp_mount (server, mount);
+        if (yp)
+        {
+            /* only force if touch */
+            if (yp->process == do_yp_touch)
+                yp->next_update = trigger;
+        }
+        server = server->next;
+    }
+    thread_rwlock_unlock (&yp_lock);
+}
+
+
+void yp_shutdown ()
+{
+    yp_running = 0;
+    yp_update = 1;
+    thread_join (yp_thread);
+    curl_global_cleanup();
+}
+

Modified: icecast/trunk/icecast/src/yp.h
===================================================================
--- icecast/trunk/icecast/src/yp.h	2004-05-09 08:13:35 UTC (rev 6645)
+++ icecast/trunk/icecast/src/yp.h	2004-05-10 16:17:56 UTC (rev 6646)
@@ -28,40 +28,26 @@
 struct source_tag;
 
 #define YP_ADD_ALL -1
-typedef struct ypdata_tag
-{
-    char *sid;
-    char *server_name;
-    char *server_desc;
-    char *server_genre;
-    char *cluster_password;
-    char *server_url;
-    char *listen_url;
-    char *bitrate;
-    char *audio_info;
-    char *server_type;
-    char *current_song;
-    char *yp_url;
-    int    yp_url_timeout;
-    long yp_last_touch;
-    int    yp_touch_interval;
-} ypdata_t;
 
-void *yp_touch_thread(void *arg);
-int yp_add(struct source_tag *source, int which);
-int yp_touch();
-int yp_remove(struct source_tag *psource);
-ypdata_t *yp_create_ypdata();
-void yp_destroy_ypdata(ypdata_t *ypdata);
-void add_yp_info(struct source_tag *source, char *stat_name, void *info, 
-     int type);
 #ifdef USE_YP
+void yp_add (struct source_tag *source);
+void yp_remove (const char *mount);
+void yp_touch (const char *mount);
 void yp_recheck_config (ice_config_t *config);
-#else
-#define yp_recheck_config(x)  do{}while(0)
-#endif
 void yp_initialize();
+void yp_shutdown();
 
+#else
+
+#define yp_add(x)               do{}while(0)
+#define yp_remove(x)            do{}while(0)
+#define yp_touch(x)             do{}while(0)
+#define yp_recheck_config(x)    do{}while(0)
+#define yp_initialize()         do{}while(0)
+#define yp_shutdown()           do{}while(0)
+
+#endif /* USE_YP */
+
 #endif
 
 

--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list