1
0
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:
Karl Heyes 2004-11-17 16:02:04 +00:00
parent 14f88b3267
commit 1e6232c531
9 changed files with 43 additions and 62 deletions

View File

@ -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>

View File

@ -164,6 +164,7 @@ The URL which icecast2 uses to communicate with the Directory server. The value
&lt;/listen-socket&gt; &lt;/listen-socket&gt;
&lt;fileserve&gt;1&lt;/fileserve&gt; &lt;fileserve&gt;1&lt;/fileserve&gt;
&lt;shoutcast-mount&gt;/live.nsv&lt;/shoutcast-mount&gt;
</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 &lt;paths&gt;&lt;webroot&gt; 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 &lt;paths&gt;&lt;webroot&gt; 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 />

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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;
} }

View File

@ -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

View File

@ -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);

View File

@ -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>