mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2025-02-02 15:07:36 -05:00
add <shoutcast-mount>. drop the hardcoded mountpoint hacks for NSV
svn path=/icecast/trunk/icecast/; revision=8213
This commit is contained in:
parent
14f88b3267
commit
1e6232c531
@ -99,6 +99,12 @@
|
|||||||
|
|
||||||
<fileserve>1</fileserve>
|
<fileserve>1</fileserve>
|
||||||
|
|
||||||
|
<!-- set the mountpoint for a shoutcast source to use, the default if not
|
||||||
|
specified is /stream but you can change it here if an alternative is
|
||||||
|
wanted or an extension is required
|
||||||
|
<shoutcast-mount>/live.nsv</shoutcast-mount>
|
||||||
|
-->
|
||||||
|
|
||||||
<paths>
|
<paths>
|
||||||
<!-- basedir is only used if chroot is enabled -->
|
<!-- basedir is only used if chroot is enabled -->
|
||||||
<basedir>@pkgdatadir@</basedir>
|
<basedir>@pkgdatadir@</basedir>
|
||||||
|
@ -164,6 +164,7 @@ The URL which icecast2 uses to communicate with the Directory server. The value
|
|||||||
</listen-socket>
|
</listen-socket>
|
||||||
|
|
||||||
<fileserve>1</fileserve>
|
<fileserve>1</fileserve>
|
||||||
|
<shoutcast-mount>/live.nsv</shoutcast-mount>
|
||||||
</pre>
|
</pre>
|
||||||
<p>This section contains miscellaneous server settings. Note that multiple listen-socket sections may be configured in order to have icecast2 listen on multiple network interfaces. If a bind-address is not specified for a particular listen-socket, then the hostname parameter will be used to specify the address that will be bound.
|
<p>This section contains miscellaneous server settings. Note that multiple listen-socket sections may be configured in order to have icecast2 listen on multiple network interfaces. If a bind-address is not specified for a particular listen-socket, then the hostname parameter will be used to specify the address that will be bound.
|
||||||
</p>
|
</p>
|
||||||
@ -183,6 +184,12 @@ This optional flag will indicate that this port will operate in 'shoutcast-compa
|
|||||||
<div class="indentedbox">
|
<div class="indentedbox">
|
||||||
This flag turns on the icecast2 fileserver from which static files can be served. All files are served relative to the path specified in the <paths><webroot> configuration setting.
|
This flag turns on the icecast2 fileserver from which static files can be served. All files are served relative to the path specified in the <paths><webroot> configuration setting.
|
||||||
</div>
|
</div>
|
||||||
|
<h4>shoutcast-mount</h4>
|
||||||
|
<div class="indentedbox">
|
||||||
|
An optional mountpoint to use when shoutcast DSP compatible clients connect. The default is /stream but can
|
||||||
|
be overridden here to use an alternative name which may include an extension that some clients require for
|
||||||
|
certain formats.
|
||||||
|
</div>
|
||||||
<p>
|
<p>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
27
src/admin.c
27
src/admin.c
@ -299,33 +299,16 @@ void admin_handle_request(client_t *client, char *uri)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mount = httpp_get_query_param(client->parser, "mount");
|
|
||||||
|
|
||||||
if (command == COMMAND_SHOUTCAST_METADATA_UPDATE) {
|
if (command == COMMAND_SHOUTCAST_METADATA_UPDATE) {
|
||||||
source_t *source;
|
|
||||||
|
|
||||||
mount = "/";
|
ice_config_t *config = config_get_config ();
|
||||||
|
httpp_set_query_param (client->parser, "mount", config->shoutcast_mount);
|
||||||
|
config_release_config ();
|
||||||
noauth = 1;
|
noauth = 1;
|
||||||
avl_tree_rlock(global.source_tree);
|
|
||||||
source = source_find_mount_raw(mount);
|
|
||||||
if (source == NULL) {
|
|
||||||
WARN2("Admin command %s on non-existent source %s",
|
|
||||||
command_string, mount);
|
|
||||||
avl_tree_unlock(global.source_tree);
|
|
||||||
client_send_400(client, "Mount / does not exist");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (source->shoutcast_compat == 0) {
|
|
||||||
ERROR0("Illegal call to change metadata, source not shoutcast compatible");
|
|
||||||
avl_tree_unlock (global.source_tree);
|
|
||||||
client_send_400 (client, "Illegal metadata call");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
avl_tree_unlock(global.source_tree);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mount = httpp_get_query_param(client->parser, "mount");
|
||||||
|
|
||||||
if(mount != NULL) {
|
if(mount != NULL) {
|
||||||
source_t *source;
|
source_t *source;
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#define CONFIG_DEFAULT_SOURCE_TIMEOUT 10
|
#define CONFIG_DEFAULT_SOURCE_TIMEOUT 10
|
||||||
#define CONFIG_DEFAULT_SOURCE_PASSWORD "changeme"
|
#define CONFIG_DEFAULT_SOURCE_PASSWORD "changeme"
|
||||||
#define CONFIG_DEFAULT_RELAY_PASSWORD "changeme"
|
#define CONFIG_DEFAULT_RELAY_PASSWORD "changeme"
|
||||||
|
#define CONFIG_DEFAULT_SHOUTCAST_MOUNT "/stream"
|
||||||
#define CONFIG_DEFAULT_ICE_LOGIN 0
|
#define CONFIG_DEFAULT_ICE_LOGIN 0
|
||||||
#define CONFIG_DEFAULT_FILESERVE 1
|
#define CONFIG_DEFAULT_FILESERVE 1
|
||||||
#define CONFIG_DEFAULT_TOUCH_FREQ 5
|
#define CONFIG_DEFAULT_TOUCH_FREQ 5
|
||||||
@ -156,6 +157,8 @@ void config_clear(ice_config_t *c)
|
|||||||
xmlFree(c->access_log);
|
xmlFree(c->access_log);
|
||||||
if (c->error_log && c->error_log != CONFIG_DEFAULT_ERROR_LOG)
|
if (c->error_log && c->error_log != CONFIG_DEFAULT_ERROR_LOG)
|
||||||
xmlFree(c->error_log);
|
xmlFree(c->error_log);
|
||||||
|
if (c->shoutcast_mount && c->shoutcast_mount != CONFIG_DEFAULT_SHOUTCAST_MOUNT)
|
||||||
|
xmlFree(c->shoutcast_mount);
|
||||||
for(i=0; i < MAX_LISTEN_SOCKETS; i++) {
|
for(i=0; i < MAX_LISTEN_SOCKETS; i++) {
|
||||||
if (c->listeners[i].bind_address) xmlFree(c->listeners[i].bind_address);
|
if (c->listeners[i].bind_address) xmlFree(c->listeners[i].bind_address);
|
||||||
}
|
}
|
||||||
@ -316,6 +319,7 @@ static void _set_defaults(ice_config_t *configuration)
|
|||||||
configuration->header_timeout = CONFIG_DEFAULT_HEADER_TIMEOUT;
|
configuration->header_timeout = CONFIG_DEFAULT_HEADER_TIMEOUT;
|
||||||
configuration->source_timeout = CONFIG_DEFAULT_SOURCE_TIMEOUT;
|
configuration->source_timeout = CONFIG_DEFAULT_SOURCE_TIMEOUT;
|
||||||
configuration->source_password = CONFIG_DEFAULT_SOURCE_PASSWORD;
|
configuration->source_password = CONFIG_DEFAULT_SOURCE_PASSWORD;
|
||||||
|
configuration->shoutcast_mount = CONFIG_DEFAULT_SHOUTCAST_MOUNT;
|
||||||
configuration->ice_login = CONFIG_DEFAULT_ICE_LOGIN;
|
configuration->ice_login = CONFIG_DEFAULT_ICE_LOGIN;
|
||||||
configuration->fileserve = CONFIG_DEFAULT_FILESERVE;
|
configuration->fileserve = CONFIG_DEFAULT_FILESERVE;
|
||||||
configuration->touch_interval = CONFIG_DEFAULT_TOUCH_FREQ;
|
configuration->touch_interval = CONFIG_DEFAULT_TOUCH_FREQ;
|
||||||
@ -412,6 +416,11 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node,
|
|||||||
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||||
configuration->master_update_interval = atoi(tmp);
|
configuration->master_update_interval = atoi(tmp);
|
||||||
xmlFree (tmp);
|
xmlFree (tmp);
|
||||||
|
} else if (strcmp(node->name, "shoutcast-mount") == 0) {
|
||||||
|
if (configuration->shoutcast_mount &&
|
||||||
|
configuration->shoutcast_mount != CONFIG_DEFAULT_SHOUTCAST_MOUNT)
|
||||||
|
xmlFree(configuration->shoutcast_mount);
|
||||||
|
configuration->shoutcast_mount = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||||
} else if (strcmp(node->name, "limits") == 0) {
|
} else if (strcmp(node->name, "limits") == 0) {
|
||||||
_parse_limits(doc, node->xmlChildrenNode, configuration);
|
_parse_limits(doc, node->xmlChildrenNode, configuration);
|
||||||
} else if (strcmp(node->name, "relay") == 0) {
|
} else if (strcmp(node->name, "relay") == 0) {
|
||||||
|
@ -96,6 +96,7 @@ typedef struct ice_config_tag
|
|||||||
int ice_login;
|
int ice_login;
|
||||||
int fileserve;
|
int fileserve;
|
||||||
|
|
||||||
|
char *shoutcast_mount;
|
||||||
char *source_password;
|
char *source_password;
|
||||||
char *admin_username;
|
char *admin_username;
|
||||||
char *admin_password;
|
char *admin_password;
|
||||||
|
@ -988,9 +988,8 @@ static void _handle_get_request(connection_t *con,
|
|||||||
if (uri != passed_uri) free (uri);
|
if (uri != passed_uri) free (uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handle_shoutcast_compatible(connection_t *con, char *source_password) {
|
void _handle_shoutcast_compatible(connection_t *con, char *mount, char *source_password) {
|
||||||
char shoutcast_password[256];
|
char shoutcast_password[256];
|
||||||
char shoutcast_source[256];
|
|
||||||
char *http_compliant;
|
char *http_compliant;
|
||||||
int http_compliant_len = 0;
|
int http_compliant_len = 0;
|
||||||
char header[4096];
|
char header[4096];
|
||||||
@ -1031,18 +1030,14 @@ void _handle_shoutcast_compatible(connection_t *con, char *source_password) {
|
|||||||
/* Here we create a valid HTTP request based of the information
|
/* Here we create a valid HTTP request based of the information
|
||||||
that was passed in via the non-HTTP style protocol above. This
|
that was passed in via the non-HTTP style protocol above. This
|
||||||
means we can use some of our existing code to handle this case */
|
means we can use some of our existing code to handle this case */
|
||||||
memset(shoutcast_source, 0, sizeof (shoutcast_source));
|
http_compliant_len = strlen(header) + strlen(mount) + 20;
|
||||||
strcpy(shoutcast_source, "SOURCE / HTTP/1.0\r\n");
|
|
||||||
http_compliant_len = strlen(shoutcast_source) +
|
|
||||||
strlen(header) + 1;
|
|
||||||
http_compliant = (char *)calloc(1, http_compliant_len);
|
http_compliant = (char *)calloc(1, http_compliant_len);
|
||||||
sprintf(http_compliant, "%s%s", shoutcast_source,
|
snprintf (http_compliant, http_compliant_len,
|
||||||
header);
|
"SOURCE %s HTTP/1.0\r\n%s", mount, header);
|
||||||
parser = httpp_create_parser();
|
parser = httpp_create_parser();
|
||||||
httpp_initialize(parser, NULL);
|
httpp_initialize(parser, NULL);
|
||||||
if (httpp_parse(parser, http_compliant,
|
if (httpp_parse(parser, http_compliant, strlen(http_compliant))) {
|
||||||
strlen(http_compliant))) {
|
_handle_source_request(con, parser, mount, SHOUTCAST_SOURCE_AUTH);
|
||||||
_handle_source_request(con, parser, "/", SHOUTCAST_SOURCE_AUTH);
|
|
||||||
free(http_compliant);
|
free(http_compliant);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1097,10 +1092,12 @@ static void *_handle_connection(void *arg)
|
|||||||
if(global.serversock[i] == con->serversock) {
|
if(global.serversock[i] == con->serversock) {
|
||||||
config = config_get_config();
|
config = config_get_config();
|
||||||
if (config->listeners[i].shoutcast_compat) {
|
if (config->listeners[i].shoutcast_compat) {
|
||||||
|
char *shoutcast_mount = strdup (config->shoutcast_mount);
|
||||||
source_password = strdup(config->source_password);
|
source_password = strdup(config->source_password);
|
||||||
config_release_config();
|
config_release_config();
|
||||||
_handle_shoutcast_compatible(con, source_password);
|
_handle_shoutcast_compatible(con, shoutcast_mount, source_password);
|
||||||
free(source_password);
|
free(source_password);
|
||||||
|
free (shoutcast_mount);
|
||||||
continue_flag = 1;
|
continue_flag = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
11
src/source.c
11
src/source.c
@ -485,20 +485,15 @@ static void source_init (source_t *source)
|
|||||||
char *listenurl, *str;
|
char *listenurl, *str;
|
||||||
int listen_url_size;
|
int listen_url_size;
|
||||||
char *s;
|
char *s;
|
||||||
char *extra = "";
|
|
||||||
|
|
||||||
if (source->format->type == FORMAT_TYPE_NSV) {
|
|
||||||
extra = "?file=stream.nsv";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 6 for max size of port */
|
/* 6 for max size of port */
|
||||||
listen_url_size = strlen("http://") + strlen(config->hostname) +
|
listen_url_size = strlen("http://") + strlen(config->hostname) +
|
||||||
strlen(":") + 6 + strlen(source->mount) + strlen(extra) + 1;
|
strlen(":") + 6 + strlen(source->mount) + 1;
|
||||||
|
|
||||||
listenurl = malloc (listen_url_size);
|
listenurl = malloc (listen_url_size);
|
||||||
memset (listenurl, '\000', listen_url_size);
|
memset (listenurl, '\000', listen_url_size);
|
||||||
snprintf (listenurl, listen_url_size, "http://%s:%d%s%s",
|
snprintf (listenurl, listen_url_size, "http://%s:%d%s",
|
||||||
config->hostname, config->port, source->mount, extra);
|
config->hostname, config->port, source->mount);
|
||||||
config_release_config();
|
config_release_config();
|
||||||
|
|
||||||
do
|
do
|
||||||
|
14
src/yp.c
14
src/yp.c
@ -479,22 +479,12 @@ static ypdata_t *create_yp_entry (source_t *source)
|
|||||||
if (url == NULL)
|
if (url == NULL)
|
||||||
break;
|
break;
|
||||||
config = config_get_config();
|
config = config_get_config();
|
||||||
if (source->format->type == FORMAT_TYPE_NSV) {
|
ret = snprintf (url, len, "http://%s:%d%s", config->hostname, config->port, source->mount);
|
||||||
ret = snprintf (url, len, "http://%s:%d%s?stream.nsv", config->hostname, config->port, source->mount);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ret = snprintf (url, len, "http://%s:%d%s", config->hostname, config->port, source->mount);
|
|
||||||
}
|
|
||||||
if (ret >= (signed)len)
|
if (ret >= (signed)len)
|
||||||
{
|
{
|
||||||
s = realloc (url, ++ret);
|
s = realloc (url, ++ret);
|
||||||
if (s) url = s;
|
if (s) url = s;
|
||||||
if (source->format->type == FORMAT_TYPE_NSV) {
|
snprintf (url, ret, "http://%s:%d%s", config->hostname, config->port, source->mount);
|
||||||
snprintf (url, ret, "http://%s:%d%s?file=stream.nsv", config->hostname, config->port, source->mount);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
snprintf (url, ret, "http://%s:%d%s", config->hostname, config->port, source->mount);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
config_release_config();
|
config_release_config();
|
||||||
yp->listen_url = util_url_escape (url);
|
yp->listen_url = util_url_escape (url);
|
||||||
|
@ -54,14 +54,7 @@
|
|||||||
<a href="auth.xsl">Click to Listen</a>
|
<a href="auth.xsl">Click to Listen</a>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
<xsl:otherwise>
|
<xsl:otherwise>
|
||||||
<xsl:choose>
|
<a href="{@mount}.m3u">Click to Listen</a>
|
||||||
<xsl:when test="content-type='video/nsv'">
|
|
||||||
<a href="{@mount}%3Ffile%3Dstream.nsv.m3u">Click to Listen</a>
|
|
||||||
</xsl:when>
|
|
||||||
<xsl:otherwise>
|
|
||||||
<a href="{@mount}.m3u">Click to Listen</a>
|
|
||||||
</xsl:otherwise>
|
|
||||||
</xsl:choose>
|
|
||||||
</xsl:otherwise>
|
</xsl:otherwise>
|
||||||
</xsl:choose>
|
</xsl:choose>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user