Commit 84a76ac3 authored by Michael Smith's avatar Michael Smith

status.xsl updates, better now.

Automatically create .m3u responses for any existing streams.
If /stream.ogg exists, you can now request /stream.ogg.m3u in your browser.

svn path=/trunk/icecast/; revision=3797
parent e97e4049
...@@ -344,6 +344,7 @@ static void *_handle_connection(void *arg) ...@@ -344,6 +344,7 @@ static void *_handle_connection(void *arg)
int bytes; int bytes;
struct stat statbuf; struct stat statbuf;
char fullPath[4096]; char fullPath[4096];
char *uri;
while (global.running == ICE_RUNNING) { while (global.running == ICE_RUNNING) {
memset(header, 0, 4096); memset(header, 0, 4096);
...@@ -376,13 +377,14 @@ static void *_handle_connection(void *arg) ...@@ -376,13 +377,14 @@ static void *_handle_connection(void *arg)
continue; continue;
} }
uri = httpp_getvar(parser, HTTPP_VAR_URI);
if (parser->req_type == httpp_req_source) { if (parser->req_type == httpp_req_source) {
INFO1("Source logging in at mountpoint \"%s\"", INFO1("Source logging in at mountpoint \"%s\"", uri);
httpp_getvar(parser, HTTPP_VAR_URI));
stats_event_inc(NULL, "source_connections"); stats_event_inc(NULL, "source_connections");
if (strcmp((httpp_getvar(parser, "ice-password") != NULL) ? httpp_getvar(parser, "ice-password") : "", (config_get_config()->source_password != NULL) ? config_get_config()->source_password : "") != 0) { if (strcmp((httpp_getvar(parser, "ice-password") != NULL) ? httpp_getvar(parser, "ice-password") : "", (config_get_config()->source_password != NULL) ? config_get_config()->source_password : "") != 0) {
INFO1("Source (%s) attempted to login with bad password", httpp_getvar(parser, HTTPP_VAR_URI)); INFO1("Source (%s) attempted to login with bad password", uri);
connection_close(con); connection_close(con);
httpp_destroy(parser); httpp_destroy(parser);
continue; continue;
...@@ -393,8 +395,8 @@ static void *_handle_connection(void *arg) ...@@ -393,8 +395,8 @@ static void *_handle_connection(void *arg)
*/ */
avl_tree_rlock(global.source_tree); avl_tree_rlock(global.source_tree);
if (source_find_mount(httpp_getvar(parser, HTTPP_VAR_URI)) != NULL) { if (source_find_mount(uri) != NULL) {
INFO1("Source tried to log in as %s, but is already used", httpp_getvar(parser, HTTPP_VAR_URI)); INFO1("Source tried to log in as %s, but is already used", uri);
connection_close(con); connection_close(con);
httpp_destroy(parser); httpp_destroy(parser);
avl_tree_unlock(global.source_tree); avl_tree_unlock(global.source_tree);
...@@ -402,7 +404,7 @@ static void *_handle_connection(void *arg) ...@@ -402,7 +404,7 @@ static void *_handle_connection(void *arg)
} }
avl_tree_unlock(global.source_tree); avl_tree_unlock(global.source_tree);
if (!connection_create_source(con, parser, httpp_getvar(parser, HTTPP_VAR_URI))) { if (!connection_create_source(con, parser, uri)) {
connection_close(con); connection_close(con);
httpp_destroy(parser); httpp_destroy(parser);
} }
...@@ -443,7 +445,7 @@ static void *_handle_connection(void *arg) ...@@ -443,7 +445,7 @@ static void *_handle_connection(void *arg)
** aren't subject to the limits. ** aren't subject to the limits.
*/ */
// TODO: add GUID-xxxxxx // TODO: add GUID-xxxxxx
if (strcmp(httpp_getvar(parser, HTTPP_VAR_URI), "/stats.xml") == 0) { if (strcmp(uri, "/stats.xml") == 0) {
DEBUG0("Stats request, sending xml stats"); DEBUG0("Stats request, sending xml stats");
stats_sendxml(client); stats_sendxml(client);
client_destroy(client); client_destroy(client);
...@@ -454,8 +456,8 @@ static void *_handle_connection(void *arg) ...@@ -454,8 +456,8 @@ static void *_handle_connection(void *arg)
** if the extension is .xsl, if so, then process ** if the extension is .xsl, if so, then process
** this request as an XSLT request ** this request as an XSLT request
*/ */
if (util_check_valid_extension(httpp_getvar(parser, HTTPP_VAR_URI)) == XSLT_CONTENT) { if (util_check_valid_extension(uri) == XSLT_CONTENT) {
util_get_full_path(httpp_getvar(parser, HTTPP_VAR_URI), fullPath, sizeof(fullPath)); util_get_full_path(uri, fullPath, sizeof(fullPath));
/* If the file exists, then transform it, otherwise, write a 404 error */ /* If the file exists, then transform it, otherwise, write a 404 error */
if (stat(fullPath, &statbuf) == 0) { if (stat(fullPath, &statbuf) == 0) {
...@@ -473,7 +475,33 @@ static void *_handle_connection(void *arg) ...@@ -473,7 +475,33 @@ static void *_handle_connection(void *arg)
continue; continue;
} }
if (strcmp(httpp_getvar(parser, HTTPP_VAR_URI), "/allstreams.txt") == 0) { if(strcmp(util_get_extension(uri), "m3u") == 0) {
char *sourceuri = strdup(uri);
char *dot = strrchr(sourceuri, '.');
*dot = 0;
avl_tree_rlock(global.source_tree);
source = source_find_mount(sourceuri);
if (source) {
client->respcode = 200;
bytes = sock_write(client->con->sock,
"HTTP/1.0 200 OK\r\nContent-Type: audio/x-mpegurl\r\n\r\nhttp://%s:%d%s",
config_get_config()->hostname,
config_get_config()->port,
sourceuri
);
}
else {
client->respcode = 404;
bytes = sock_write(client->con->sock,
"HTTP/1.0 404 Not Found\r\nContent-Type: text/html\r\n<b>The file you requested could not be found</b>\r\n");
}
avl_tree_unlock(global.source_tree);
if(bytes > 0) client->con->sent_bytes = bytes;
client_destroy(client);
continue;
}
if (strcmp(uri, "/allstreams.txt") == 0) {
if (strcmp((httpp_getvar(parser, "ice-password") != NULL) ? httpp_getvar(parser, "ice-password") : "", (config_get_config()->source_password != NULL) ? config_get_config()->source_password : "") != 0) { if (strcmp((httpp_getvar(parser, "ice-password") != NULL) ? httpp_getvar(parser, "ice-password") : "", (config_get_config()->source_password != NULL) ? config_get_config()->source_password : "") != 0) {
INFO0("Client attempted to fetch allstreams.txt with bad password"); INFO0("Client attempted to fetch allstreams.txt with bad password");
if (parser->req_type == httpp_req_get) { if (parser->req_type == httpp_req_get) {
...@@ -518,7 +546,7 @@ static void *_handle_connection(void *arg) ...@@ -518,7 +546,7 @@ static void *_handle_connection(void *arg)
global_unlock(); global_unlock();
avl_tree_rlock(global.source_tree); avl_tree_rlock(global.source_tree);
source = source_find_mount(httpp_getvar(parser, HTTPP_VAR_URI)); source = source_find_mount(uri);
if (source) { if (source) {
DEBUG0("Source found for client"); DEBUG0("Source found for client");
......
...@@ -19,6 +19,8 @@ typedef struct _format_plugin_tag ...@@ -19,6 +19,8 @@ typedef struct _format_plugin_tag
/* we need to know the mount to report statistics */ /* we need to know the mount to report statistics */
char *mount; char *mount;
char *format_description;
/* set this is the data format has a header that /* set this is the data format has a header that
** we must send before regular data ** we must send before regular data
*/ */
......
...@@ -28,6 +28,7 @@ format_plugin_t *format_mp3_get_plugin(void) ...@@ -28,6 +28,7 @@ format_plugin_t *format_mp3_get_plugin(void)
plugin->get_buffer = format_mp3_get_buffer; plugin->get_buffer = format_mp3_get_buffer;
plugin->get_predata = format_mp3_get_predata; plugin->get_predata = format_mp3_get_predata;
plugin->free_plugin = format_mp3_free_plugin; plugin->free_plugin = format_mp3_free_plugin;
plugin->format_description = "MP3 audio";
plugin->_state = NULL; plugin->_state = NULL;
......
...@@ -52,6 +52,7 @@ format_plugin_t *format_vorbis_get_plugin(void) ...@@ -52,6 +52,7 @@ format_plugin_t *format_vorbis_get_plugin(void)
plugin->get_buffer = format_vorbis_get_buffer; plugin->get_buffer = format_vorbis_get_buffer;
plugin->get_predata = format_vorbis_get_predata; plugin->get_predata = format_vorbis_get_predata;
plugin->free_plugin = format_vorbis_free_plugin; plugin->free_plugin = format_vorbis_free_plugin;
plugin->format_description = "Ogg Vorbis";
state = (vstate_t *)calloc(1, sizeof(vstate_t)); state = (vstate_t *)calloc(1, sizeof(vstate_t));
ogg_sync_init(&state->oy); ogg_sync_init(&state->oy);
......
...@@ -139,10 +139,13 @@ void *source_main(void *arg) ...@@ -139,10 +139,13 @@ void *source_main(void *arg)
stats_event(source->mount, "name", s); stats_event(source->mount, "name", s);
if ((s = httpp_getvar(source->parser, "ice-url"))) if ((s = httpp_getvar(source->parser, "ice-url")))
stats_event(source->mount, "url", s); stats_event(source->mount, "url", s);
if ((s = httpp_getvar(source->parser, "ice-genre")))
stats_event(source->mount, "genre", s);
if ((s = httpp_getvar(source->parser, "ice-bitrate"))) if ((s = httpp_getvar(source->parser, "ice-bitrate")))
stats_event(source->mount, "bitrate", s); stats_event(source->mount, "bitrate", s);
if ((s = httpp_getvar(source->parser, "ice-description"))) if ((s = httpp_getvar(source->parser, "ice-description")))
stats_event(source->mount, "description", s); stats_event(source->mount, "description", s);
stats_event(source->mount, "type", source->format->format_description);
while (global.running == ICE_RUNNING) { while (global.running == ICE_RUNNING) {
ret = source->format->get_buffer(source->format, NULL, 0, &refbuf); ret = source->format->get_buffer(source->format, NULL, 0, &refbuf);
......
...@@ -96,12 +96,21 @@ int util_get_full_path(char *uri, char *fullPath, int fullPathLen) { ...@@ -96,12 +96,21 @@ int util_get_full_path(char *uri, char *fullPath, int fullPathLen) {
int ret = 0; int ret = 0;
if (uri) { if (uri) {
memset(fullPath, '\000', fullPathLen); memset(fullPath, '\000', fullPathLen);
snprintf(fullPath, fullPathLen-1, "%s%s%s", config_get_config()->webroot_dir, PATH_SEPARATOR, uri); snprintf(fullPath, fullPathLen-1, "%s%s", config_get_config()->webroot_dir, uri);
ret = 1; ret = 1;
} }
return ret; return ret;
} }
char *util_get_extension(char *path) {
char *ext = strrchr(path, '.');
if(ext == NULL)
return "";
else
return ext+1;
}
int util_check_valid_extension(char *uri) { int util_check_valid_extension(char *uri) {
int ret = 0; int ret = 0;
char *p2; char *p2;
......
...@@ -8,5 +8,6 @@ int util_timed_wait_for_fd(int fd, int timeout); ...@@ -8,5 +8,6 @@ int util_timed_wait_for_fd(int fd, int timeout);
int util_read_header(int sock, char *buff, unsigned long len); int util_read_header(int sock, char *buff, unsigned long len);
int util_get_full_path(char *uri, char *fullPath, int fullPathLen); int util_get_full_path(char *uri, char *fullPath, int fullPathLen);
int util_check_valid_extension(char *uri); int util_check_valid_extension(char *uri);
char *util_get_extension(char *path);
#endif /* __UTIL_H__ */ #endif /* __UTIL_H__ */
...@@ -55,9 +55,16 @@ a:hover {color: black; font-family:Verdana} ...@@ -55,9 +55,16 @@ a:hover {color: black; font-family:Verdana}
<tr> <tr>
<td bgcolor="#5BB2EB" colspan="2" align="center"> <td bgcolor="#5BB2EB" colspan="2" align="center">
<center> <center>
<xsl:choose>
<xsl:when test="listeners">
<font class="mount">Current Stream Information<br></br> <font class="mount">Current Stream Information<br></br>
<xsl:value-of select="@mount" /> <xsl:value-of select="@mount" />
</font> </font>
</xsl:when>
<xsl:otherwise>
<font class="mount">Stream Information (stream not currently available)</font>
</xsl:otherwise>
</xsl:choose>
</center> </center>
</td> </td>
</tr> </tr>
...@@ -80,14 +87,27 @@ a:hover {color: black; font-family:Verdana} ...@@ -80,14 +87,27 @@ a:hover {color: black; font-family:Verdana}
</tr> </tr>
<tr> <tr>
<td width="100" > <td width="100" >
<font class="default1">Stream Status: </font> <font class="default1">Stream Type: </font>
</td> </td>
<td> <td>
<font class="default2"> <font class="default2">
<b><xsl:value-of select="listeners" /> listeners</b> <b><xsl:value-of select="type" /></b>
</font> </font>
</td> </td>
</tr> </tr>
<xsl:if test="listeners">
<tr>
<td width="100" >
<font class="default1">Stream Listeners: </font>
</td>
<td>
<font class="default2">
<b><xsl:value-of select="listeners" /></b>
</font>
</td>
</tr>
</xsl:if>
<xsl:if test="name">
<tr> <tr>
<td width="100" > <td width="100" >
<font class="default1">Stream Title: </font> <font class="default1">Stream Title: </font>
...@@ -98,6 +118,8 @@ a:hover {color: black; font-family:Verdana} ...@@ -98,6 +118,8 @@ a:hover {color: black; font-family:Verdana}
</font> </font>
</td> </td>
</tr> </tr>
</xsl:if>
<xsl:if test="genre">
<tr> <tr>
<td width="100" > <td width="100" >
<font class="default1">Stream Genre: </font> <font class="default1">Stream Genre: </font>
...@@ -108,6 +130,8 @@ a:hover {color: black; font-family:Verdana} ...@@ -108,6 +130,8 @@ a:hover {color: black; font-family:Verdana}
</font> </font>
</td> </td>
</tr> </tr>
</xsl:if>
<xsl:if test="description">
<tr> <tr>
<td width="100" > <td width="100" >
<font class="default1">Stream Description: </font> <font class="default1">Stream Description: </font>
...@@ -118,6 +142,8 @@ a:hover {color: black; font-family:Verdana} ...@@ -118,6 +142,8 @@ a:hover {color: black; font-family:Verdana}
</font> </font>
</td> </td>
</tr> </tr>
</xsl:if>
<xsl:if test="url">
<tr> <tr>
<td width="100" > <td width="100" >
<font class="default1">Stream URL: </font> <font class="default1">Stream URL: </font>
...@@ -130,6 +156,7 @@ a:hover {color: black; font-family:Verdana} ...@@ -130,6 +156,7 @@ a:hover {color: black; font-family:Verdana}
</font> </font>
</td> </td>
</tr> </tr>
</xsl:if>
<tr> <tr>
<td width="100" > <td width="100" >
<font class="default1">Current Song: </font> <font class="default1">Current Song: </font>
...@@ -140,16 +167,18 @@ a:hover {color: black; font-family:Verdana} ...@@ -140,16 +167,18 @@ a:hover {color: black; font-family:Verdana}
</font> </font>
</td> </td>
</tr> </tr>
<xsl:if test="listeners">
<tr> <tr>
<td width="100" > <td width="100" >
<font class="default1">Listen: </font> <font class="default1">Listen: </font>
</td> </td>
<td> <td>
<font class="default2"> <font class="default2">
<a href="{@mount}">Here</a> <a href="{@mount}.m3u">Here</a>
</font> </font>
</td> </td>
</tr> </tr>
</xsl:if>
</table> </table>
<table cellpadding="0" cellspacing="0" border="0" width="100%"> <table cellpadding="0" cellspacing="0" border="0" width="100%">
<tr> <tr>
......
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