Commit 79adab01 authored by Karl Heyes's avatar Karl Heyes

allow for more updating over HUP. Made the YP engine only read the stats instead

of updating them, so source header parsing is done in the apply mount. Per-mount
stream settings also allow for overriding the incoming settings.

svn path=/icecast/trunk/icecast/; revision=9325
parent d57a19ac
......@@ -347,7 +347,14 @@ If you are relaying a Shoutcast stream, you need to specify this indicator to al
<dump-file>/tmp/dump-example1.ogg</dump-file>
<fallback-mount>/example2.ogg</fallback-mount>
<fallback-override>1</fallback-override>
<no-yp>1</no-yp>
<public>1</public>
<stream-name>My audio stream</stream-name>
<stream-description>My audio description</stream-description>
<stream-url>http://some.place.com</stream-url>
<genre>classical</genre>
<bitrate>64</bitrate>
<type>application/ogg</type>
<subtype>vorbis</subtype>
<hidden>1</hidden>
<burst-size>65536</burst-size>
<mp3-metadata-interval>4096</mp3-metadata-interval>
......@@ -358,7 +365,16 @@ If you are relaying a Shoutcast stream, you need to specify this indicator to al
</mount>
</pre>
<p>This section contains settings which apply only to a specific mountpoint. Within this section you can reserve a specific mountpoint and set a source username/password for that mountpoint (not yet implemented) as well as specify individual settings which will apply only to the supplied mountpoint.
<p>This section contains the settings which apply only to a specific mountpoint and applies to
an incoming stream whether it is a relay or a source client. The purpose of the mount definition
is to state certain information that can override either global/default settings or settings
provided from the incoming stream.
</p>
<p>A mount does not need to be stated for each incoming source although you may want to
specific certain settings like the maximum number of listeners or a mountpoint specific
username/password. As a general rule, only define what you need to but each mount definition
needs at least the mount-name. Changes to most of these will apply across a configuration file
re-read even on active streams, however some only apply when the stream starts or ends.
</p>
<h4>mount-name</h4>
<div class="indentedbox">
......@@ -397,11 +413,67 @@ This multi-level fallback allows clients to cascade several mountpoints.
When enabled, this allows a connecting source client or relay on this mountpoint to move
listening clients back from the fallback mount.
</div>
<h4>no-yp</h4>
<h4>no-yp (deprecated)</h4>
<div class="indentedbox">
<p>Setting this option prevents this mountpoint from advertising on YP. The default is 0
so YP advertising can occur however you may want to prevent it here if you intend listeners
to connect to a local relay instead. Deprecated option, replaced by &lt;public&gt;
</p>
</div>
<h4>public</h4>
<div class="indentedbox">
<p>The default setting for this is -1 indicating that it is up to the source client or
relay to determine if this mountpoint should advertise. A setting of 0 will prevent any
advertising and a setting of 1 will force it to advertise. If you do force advertising
you may need to set other settings listed below as the YP server can refuse to advertise
if there is not enough information provided.
</p>
</div>
<h4>stream-name</h4>
<div class="indentedbox">
<p>Setting this will add the specified name to the stats (and therefore YP) for this
mountpoint even if the source client/relay provide one.
</p>
</div>
<h4>stream-description</h4>
<div class="indentedbox">
<p>Setting this will add the specified description to the stats (and therefore YP) for
this mountpoint even if the source client/relay provide one.
</p>
</div>
<h4>stream-url</h4>
<div class="indentedbox">
<p>Setting this will add the specified URL to the stats (and therefore YP) for this
mountpoint even if the source client/relay provide one. The URL is generally for
directing people to a website.
</p>
</div>
<h4>genre</h4>
<div class="indentedbox">
<p>Setting this will add the specified genre to the stats (and therefore YP) for this
mountpoint even if the source client/relay provide one. This can be anything be using
certain key words can help searches in the YP directories.
</p>
</div>
<h4>bitrate</h4>
<div class="indentedbox">
<p>Setting this will add the specified bitrate to the stats (and therefore YP) for this
mountpoint even if the source client/relay provide one. This is stated in kbps.
</p>
</div>
<h4>type</h4>
<div class="indentedbox">
<p>Setting this will add the specified mime type to the stats (and therefore YP) for
this mountpoint even if the source client/relay provide one. It is very unlikely that
this will be needed.
</p>
</div>
<h4>subtype</h4>
<div class="indentedbox">
Setting this option prevents this mountpoint from advertising on YP. The default is 0 so YP
advertising occurs however you may want to prevent it here if you intend listeners to connect
to a local relay instead
<p>Setting this will add the specified subtype to the stats (and therefore YP) for
this mountpoint. The subtype is really to help the YP server to identify the components
of the type. An example setting is vorbis/theora do indicate the codecs in an Ogg stream
</p>
</div>
<h4>burst-size</h4>
<div class="indentedbox">
......
......@@ -191,6 +191,12 @@ void config_clear(ice_config_t *c)
xmlFree(mount->password);
xmlFree(mount->dumpfile);
xmlFree(mount->fallback_mount);
xmlFree(mount->stream_name);
xmlFree(mount->stream_description);
xmlFree(mount->stream_url);
xmlFree(mount->stream_genre);
xmlFree(mount->bitrate);
xmlFree(mount->type);
if (mount->cluster_password) {
xmlFree(mount->cluster_password);
}
......@@ -529,6 +535,7 @@ static void _parse_mount(xmlDocPtr doc, xmlNodePtr node,
mount->max_listeners = -1;
mount->burst_size = -1;
mount->mp3_meta_interval = -1;
mount->yp_public = -1;
mount->next = NULL;
do {
......@@ -577,7 +584,7 @@ static void _parse_mount(xmlDocPtr doc, xmlNodePtr node,
}
else if (strcmp(node->name, "no-yp") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
mount->no_yp = atoi(tmp);
mount->yp_public = atoi(tmp) == 0 ? -1 : 0;
if(tmp) xmlFree(tmp);
}
else if (strcmp(node->name, "hidden") == 0) {
......@@ -635,10 +642,36 @@ static void _parse_mount(xmlDocPtr doc, xmlNodePtr node,
} else if (strcmp(node->name, "cluster-password") == 0) {
mount->cluster_password = (char *)xmlNodeListGetString(
doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "stream-name") == 0) {
mount->stream_name = (char *)xmlNodeListGetString(
doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "stream-description") == 0) {
mount->stream_description = (char *)xmlNodeListGetString(
doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "stream-url") == 0) {
mount->stream_url = (char *)xmlNodeListGetString(
doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "genre") == 0) {
mount->stream_genre = (char *)xmlNodeListGetString(
doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "bitrate") == 0) {
mount->bitrate = (char *)xmlNodeListGetString(
doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "public") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
mount->yp_public = atoi (tmp);
if(tmp) xmlFree(tmp);
} else if (strcmp(node->name, "type") == 0) {
mount->type = (char *)xmlNodeListGetString(
doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "subtype") == 0) {
mount->subtype = (char *)xmlNodeListGetString(
doc, node->xmlChildrenNode, 1);
}
} while ((node = node->next));
}
static void _parse_relay(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *configuration)
{
......
......@@ -57,7 +57,6 @@ typedef struct _mount_proxy {
int burst_size; /* amount to send to a new client if possible, -1 take
* from global setting */
unsigned int queue_size_limit;
int no_yp; /* Do we prevent YP on this mount */
int hidden; /* Do we list this on the xsl pages */
unsigned int source_timeout; /* source timeout in seconds */
int mp3_meta_interval; /* outgoing per-stream metadata interval */
......@@ -65,6 +64,16 @@ typedef struct _mount_proxy {
char *auth_type; /* Authentication type */
char *cluster_password;
config_options_t *auth_options; /* Options for this type */
char *stream_name;
char *stream_description;
char *stream_url;
char *stream_genre;
char *bitrate;
char *type;
char *subtype;
int yp_public;
struct _mount_proxy *next;
} mount_proxy;
......
......@@ -449,6 +449,7 @@ int connection_complete_source (source_t *source)
if (global.sources < config->source_limit)
{
char *contenttype;
mount_proxy *mountinfo;
format_type_t format_type;
/* setup format handler */
......@@ -488,11 +489,6 @@ int connection_complete_source (source_t *source)
global.sources++;
global_unlock();
/* set global settings first */
source->queue_size_limit = config->queue_size_limit;
source->timeout = config->source_timeout;
source->burst_size = config->burst_size;
/* for relays, we don't yet have a client, however we do require one
* to retrieve the stream from. This is created here, quite late,
* because we can't use this client to return an error code/message,
......@@ -515,7 +511,11 @@ int connection_complete_source (source_t *source)
}
}
source_update_settings (config, source);
source->running = 1;
mountinfo = config_find_mount (config, source->mount);
if (mountinfo == NULL)
source_update_settings (config, source, mountinfo);
source_recheck_mounts ();
config_release_config();
source->shutdown_rwlock = &_source_shutdown_rwlock;
......
......@@ -201,7 +201,7 @@ static void format_mp3_apply_settings (client_t *client, format_plugin_t *format
{
mp3_state *source_mp3 = format->_state;
if (mount->mp3_meta_interval <= 0)
if (mount== NULL || mount->mp3_meta_interval <= 0)
{
char *metadata = httpp_getvar (client->parser, "icy-metaint");
source_mp3->interval = -1;
......@@ -214,7 +214,7 @@ static void format_mp3_apply_settings (client_t *client, format_plugin_t *format
}
else
source_mp3->interval = mount->mp3_meta_interval;
DEBUG2 ("mp3 interval %d, %d", mount->mp3_meta_interval, source_mp3->interval);
DEBUG1 ("mp3 interval %d", source_mp3->interval);
}
......
This diff is collapsed.
......@@ -78,7 +78,7 @@ typedef struct source_tag
source_t *source_reserve (const char *mount);
void *source_client_thread (void *arg);
void source_update_settings (ice_config_t *config, source_t *source);
void source_update_settings (ice_config_t *config, source_t *source, mount_proxy *mountinfo);
void source_clear_source (source_t *source);
source_t *source_find_mount(const char *mount);
source_t *source_find_mount_raw(const char *mount);
......
......@@ -92,7 +92,7 @@ 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 void add_yp_info (ypdata_t *yp, 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);
......@@ -334,12 +334,37 @@ static unsigned do_yp_add (ypdata_t *yp, char *s, unsigned len)
int ret;
char *value;
value = stats_get_value (yp->mount, "server_type");
add_yp_info (yp, value, YP_SERVER_TYPE);
free (value);
value = stats_get_value (yp->mount, "server_name");
add_yp_info (yp, value, YP_SERVER_NAME);
free (value);
value = stats_get_value (yp->mount, "server_url");
add_yp_info (yp, value, YP_SERVER_URL);
free (value);
value = stats_get_value (yp->mount, "genre");
add_yp_info (yp, value, YP_SERVER_GENRE);
free (value);
value = stats_get_value (yp->mount, "bitrate");
add_yp_info (yp, value, YP_BITRATE);
free (value);
value = stats_get_value (yp->mount, "server_description");
add_yp_info (yp, value, YP_SERVER_DESC);
free (value);
value = stats_get_value (yp->mount, "subtype");
if (value)
{
add_yp_info (yp, "subtype", value, YP_SUBTYPE);
free (value);
}
add_yp_info (yp, value, YP_SUBTYPE);
free (value);
value = stats_get_value (yp->mount, "audio_info");
add_yp_info (yp, value, YP_AUDIO_INFO);
free (value);
ret = snprintf (s, len, "action=add&sn=%s&genre=%s&cpswd=%s&desc="
"%s&url=%s&listenurl=%s&type=%s&stype=%s&b=%s&%s\r\n",
......@@ -382,7 +407,8 @@ static unsigned do_yp_touch (ypdata_t *yp, char *s, unsigned len)
if (song)
{
sprintf (song, "%s%s%s", artist, separator, title);
add_yp_info(yp, "yp_currently_playing", song, YP_CURRENT_SONG);
add_yp_info(yp, song, YP_CURRENT_SONG);
stats_event (yp->mount, "yp_currently_playing", song);
free (song);
}
}
......@@ -404,7 +430,7 @@ static unsigned do_yp_touch (ypdata_t *yp, char *s, unsigned len)
val = stats_get_value (yp->mount, "subtype");
if (val)
{
add_yp_info (yp, "subtype", val, YP_SUBTYPE);
add_yp_info (yp, val, YP_SUBTYPE);
free (val);
}
......@@ -472,13 +498,11 @@ static void yp_process_server (struct yp_server *server)
static ypdata_t *create_yp_entry (source_t *source)
static ypdata_t *create_yp_entry (const char *mount)
{
ypdata_t *yp;
char *s;
if (source->running == 0 || source->yp_public == 0)
return NULL;
yp = calloc (1, sizeof (ypdata_t));
do
{
......@@ -490,7 +514,7 @@ static ypdata_t *create_yp_entry (source_t *source)
if (yp == NULL)
break;
yp->mount = strdup (source->mount);
yp->mount = strdup (mount);
yp->server_name = strdup ("");
yp->server_desc = strdup ("");
yp->server_genre = strdup ("");
......@@ -507,17 +531,17 @@ static ypdata_t *create_yp_entry (source_t *source)
if (url == NULL)
break;
config = config_get_config();
ret = snprintf (url, len, "http://%s:%d%s", config->hostname, config->port, source->mount);
ret = snprintf (url, len, "http://%s:%d%s", config->hostname, config->port, 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);
snprintf (url, ret, "http://%s:%d%s", config->hostname, config->port, mount);
}
mountproxy = config_find_mount (config, source->mount);
mountproxy = config_find_mount (config, mount);
if (mountproxy && mountproxy->cluster_password)
add_yp_info (yp, "cluster_password", mountproxy->cluster_password, YP_CLUSTER_PASSWORD);
add_yp_info (yp, mountproxy->cluster_password, YP_CLUSTER_PASSWORD);
config_release_config();
yp->listen_url = util_url_escape (url);
......@@ -525,39 +549,6 @@ static ypdata_t *create_yp_entry (source_t *source)
if (yp->listen_url == NULL)
break;
/* ice-* is icecast, icy-* is shoutcast */
add_yp_info (yp, "server_type", source->format->contenttype, YP_SERVER_TYPE);
if ((s = httpp_getvar(source->parser, "ice-name"))) {
add_yp_info (yp, "server_name", s, YP_SERVER_NAME);
}
if ((s = httpp_getvar(source->parser, "icy-name"))) {
add_yp_info (yp, "server_name", s, YP_SERVER_NAME);
}
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);
......@@ -606,7 +597,7 @@ static void check_servers ()
ypdata_t *yp;
source_t *source = node->key;
if ((yp = create_yp_entry (source)) != NULL)
if ((yp = create_yp_entry (source->mount)) != NULL)
{
DEBUG1 ("Adding existing mount %s", source->mount);
yp->server = server;
......@@ -764,7 +755,7 @@ static void yp_destroy_ypdata(ypdata_t *ypdata)
}
}
static void add_yp_info (ypdata_t *yp, char *stat_name, void *info, int type)
static void add_yp_info (ypdata_t *yp, void *info, int type)
{
char *escaped;
......@@ -780,7 +771,6 @@ static void add_yp_info (ypdata_t *yp, char *stat_name, void *info, int type)
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:
......@@ -790,7 +780,6 @@ static void add_yp_info (ypdata_t *yp, char *stat_name, void *info, int type)
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:
......@@ -800,7 +789,6 @@ static void add_yp_info (ypdata_t *yp, char *stat_name, void *info, int type)
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:
......@@ -810,7 +798,6 @@ static void add_yp_info (ypdata_t *yp, char *stat_name, void *info, int type)
if (yp->url)
free (yp->url);
yp->url = escaped;
stats_event (yp->mount, stat_name, (char *)info);
}
break;
case YP_BITRATE:
......@@ -820,13 +807,15 @@ static void add_yp_info (ypdata_t *yp, char *stat_name, void *info, int type)
if (yp->bitrate)
free (yp->bitrate);
yp->bitrate = escaped;
stats_event (yp->mount, stat_name, (char *)info);
}
break;
case YP_AUDIO_INFO:
if (yp->audio_info)
escaped = util_url_escape(info);
if (escaped)
{
free (yp->audio_info);
yp->audio_info = strdup (info);
yp->audio_info = escaped;
}
break;
case YP_SERVER_TYPE:
escaped = util_url_escape(info);
......@@ -844,7 +833,6 @@ static void add_yp_info (ypdata_t *yp, char *stat_name, void *info, int type)
if (yp->current_song)
free (yp->current_song);
yp->current_song = escaped;
stats_event (yp->mount, "yp_currently_playing", (char *)info);
}
break;
case YP_CLUSTER_PASSWORD:
......@@ -869,7 +857,7 @@ static void add_yp_info (ypdata_t *yp, char *stat_name, void *info, int type)
/* Add YP entries to active servers */
void yp_add (source_t *source)
void yp_add (const char *mount)
{
struct yp_server *server;
......@@ -883,9 +871,9 @@ void yp_add (source_t *source)
{
ypdata_t *yp;
/* add new ypdata to each servers pending yp */
if ((yp = create_yp_entry (source)) != NULL)
if ((yp = create_yp_entry (mount)) != NULL)
{
DEBUG2 ("Adding %s to %s", source->mount, server->url);
DEBUG2 ("Adding %s to %s", mount, server->url);
yp->server = server;
yp->touch_interval = server->touch_interval;
yp->next = server->pending_mounts;
......
......@@ -25,12 +25,10 @@
#define YP_CLUSTER_PASSWORD 9
#define YP_SUBTYPE 10
struct source_tag;
#define YP_ADD_ALL -1
#ifdef USE_YP
void yp_add (struct source_tag *source);
void yp_add (const char *mount);
void yp_remove (const char *mount);
void yp_touch (const char *mount);
void yp_recheck_config (ice_config_t *config);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment