[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 (¤t_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