mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-12-04 14:46:30 -05:00
oddsock's xslt stats support, slightly cleaned up
svn path=/trunk/icecast/; revision=3772
This commit is contained in:
parent
3fdf565bc9
commit
9b6b2afeaf
@ -32,6 +32,7 @@
|
|||||||
<paths>
|
<paths>
|
||||||
<basedir>/usr/local/icecast</basedir>
|
<basedir>/usr/local/icecast</basedir>
|
||||||
<logdir>/tmp</logdir>
|
<logdir>/tmp</logdir>
|
||||||
|
<webroot>/usr/local/icecast/webroot</basedir>
|
||||||
</paths>
|
</paths>
|
||||||
|
|
||||||
<logging>
|
<logging>
|
||||||
|
@ -11,20 +11,17 @@ noinst_HEADERS = config.h os.h logging.h sighandler.h connection.h global.h\
|
|||||||
compat.h format_mp3.h
|
compat.h format_mp3.h
|
||||||
icecast_SOURCES = config.c main.c logging.c sighandler.c connection.c global.c\
|
icecast_SOURCES = config.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\
|
util.c slave.c source.c stats.c refbuf.c client.c format.c format_vorbis.c\
|
||||||
format_mp3.c
|
format_mp3.c xslt.c
|
||||||
|
|
||||||
icecast_LDADD = net/libicenet.la thread/libicethread.la httpp/libicehttpp.la\
|
icecast_LDADD = net/libicenet.la thread/libicethread.la httpp/libicehttpp.la\
|
||||||
log/libicelog.la avl/libiceavl.la timing/libicetiming.la
|
log/libicelog.la avl/libiceavl.la timing/libicetiming.la
|
||||||
|
|
||||||
LIBS = @LIBS@ -lpthread @SOCKET_LIBS@ @XML_LIBS@ @OGG_LIBS@ @VORBIS_LIBS@
|
LIBS = @LIBS@ -lxslt -lpthread @SOCKET_LIBS@ @XML_LIBS@ @OGG_LIBS@ @VORBIS_LIBS@
|
||||||
CFLAGS = @CFLAGS@ @XML_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@
|
CFLAGS = -g @CFLAGS@ @XML_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@
|
||||||
|
|
||||||
INCLUDES = -I$(srcdir)/net -I$(srcdir)/thread -I$(srcdir)/avl -I$(srcdir)/httpp \
|
INCLUDES = -I$(srcdir)/net -I$(srcdir)/thread -I$(srcdir)/avl -I$(srcdir)/httpp \
|
||||||
-I$(srcdir)/log -I$(srcdir)/timing
|
-I$(srcdir)/log -I$(srcdir)/timing
|
||||||
|
|
||||||
# SCCS stuff (for BitKeeper)
|
|
||||||
GET = true
|
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
$(MAKE) all CFLAGS="@DEBUG@ @XML_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@"
|
$(MAKE) all CFLAGS="@DEBUG@ @XML_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@"
|
||||||
|
|
||||||
|
@ -28,9 +28,11 @@
|
|||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#define CONFIG_DEFAULT_BASE_DIR "/usr/local/icecast"
|
#define CONFIG_DEFAULT_BASE_DIR "/usr/local/icecast"
|
||||||
#define CONFIG_DEFAULT_LOG_DIR "/usr/local/icecast/logs"
|
#define CONFIG_DEFAULT_LOG_DIR "/usr/local/icecast/logs"
|
||||||
|
#define CONFIG_DEFAULT_WEBROOT_DIR "/usr/local/icecast/webroot"
|
||||||
#else
|
#else
|
||||||
#define CONFIG_DEFAULT_BASE_DIR ".\\"
|
#define CONFIG_DEFAULT_BASE_DIR ".\\"
|
||||||
#define CONFIG_DEFAULT_LOG_DIR ".\\logs"
|
#define CONFIG_DEFAULT_LOG_DIR ".\\logs"
|
||||||
|
#define CONFIG_DEFAULT_WEBROOT_DIR ".\\webroot"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ice_config_t _configuration;
|
ice_config_t _configuration;
|
||||||
@ -278,6 +280,9 @@ static void _parse_paths(xmlDocPtr doc, xmlNodePtr node)
|
|||||||
} else if (strcmp(node->name, "logdir") == 0) {
|
} else if (strcmp(node->name, "logdir") == 0) {
|
||||||
if (_configuration.log_dir) free(_configuration.log_dir);
|
if (_configuration.log_dir) free(_configuration.log_dir);
|
||||||
_configuration.log_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
_configuration.log_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||||
|
} else if (strcmp(node->name, "webroot") == 0) {
|
||||||
|
if (_configuration.webroot_dir) free(_configuration.webroot_dir);
|
||||||
|
_configuration.webroot_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||||
}
|
}
|
||||||
} while ((node = node->next));
|
} while ((node = node->next));
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ typedef struct ice_config_tag
|
|||||||
|
|
||||||
char *base_dir;
|
char *base_dir;
|
||||||
char *log_dir;
|
char *log_dir;
|
||||||
|
char *webroot_dir;
|
||||||
|
|
||||||
char *access_log;
|
char *access_log;
|
||||||
char *error_log;
|
char *error_log;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
@ -32,6 +33,7 @@
|
|||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
#include "xslt.h"
|
||||||
|
|
||||||
#include "source.h"
|
#include "source.h"
|
||||||
|
|
||||||
@ -333,6 +335,8 @@ static void *_handle_connection(void *arg)
|
|||||||
http_var_t *var;
|
http_var_t *var;
|
||||||
client_t *client;
|
client_t *client;
|
||||||
int bytes;
|
int bytes;
|
||||||
|
struct stat statbuf;
|
||||||
|
char fullPath[4096];
|
||||||
|
|
||||||
while (global.running == ICE_RUNNING) {
|
while (global.running == ICE_RUNNING) {
|
||||||
memset(header, 0, 4096);
|
memset(header, 0, 4096);
|
||||||
@ -437,6 +441,27 @@ static void *_handle_connection(void *arg)
|
|||||||
if (strcmp(httpp_getvar(parser, HTTPP_VAR_URI), "/stats.xml") == 0) {
|
if (strcmp(httpp_getvar(parser, HTTPP_VAR_URI), "/stats.xml") == 0) {
|
||||||
printf("sending stats.xml\n");
|
printf("sending stats.xml\n");
|
||||||
stats_sendxml(client);
|
stats_sendxml(client);
|
||||||
|
client_destroy(client);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Here we are parsing the URI request to see
|
||||||
|
** if the extension is .xsl, if so, then process
|
||||||
|
** this request as an XSLT request
|
||||||
|
*/
|
||||||
|
if (util_check_valid_extension(httpp_getvar(parser, HTTPP_VAR_URI)) == XSLT_CONTENT) {
|
||||||
|
util_get_full_path(httpp_getvar(parser, HTTPP_VAR_URI), fullPath, sizeof(fullPath));
|
||||||
|
|
||||||
|
/* If the file exists, then transform it, otherwise, write a 404 error */
|
||||||
|
if (stat(fullPath, &statbuf) == 0) {
|
||||||
|
sock_write(client->con->sock, "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
||||||
|
stats_transform_xslt(client, fullPath);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sock_write(client->con->sock, "HTTP/1.0 404 File Not Found\r\nContent-Type: text/html\r\n\r\n"\
|
||||||
|
"<b>The file you requested could not be found.</b>\r\n");
|
||||||
|
}
|
||||||
|
client_destroy(client);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
40
src/stats.c
40
src/stats.c
@ -18,6 +18,7 @@
|
|||||||
#include "refbuf.h"
|
#include "refbuf.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
|
#include "xslt.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define vsnprintf _vsnprintf
|
#define vsnprintf _vsnprintf
|
||||||
@ -728,6 +729,45 @@ static xmlNodePtr _find_xml_node(char *mount, source_xml_t **list, xmlNodePtr ro
|
|||||||
return node->node;
|
return node->node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stats_transform_xslt(client_t *client, char *xslpath)
|
||||||
|
{
|
||||||
|
xmlDocPtr doc;
|
||||||
|
|
||||||
|
stats_get_xml(&doc);
|
||||||
|
|
||||||
|
transformXSLT(doc, xslpath, client);
|
||||||
|
|
||||||
|
xmlFreeDoc(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stats_get_xml(xmlDocPtr *doc)
|
||||||
|
{
|
||||||
|
stats_event_t *event;
|
||||||
|
stats_event_t *queue;
|
||||||
|
xmlNodePtr node, srcnode;
|
||||||
|
source_xml_t *src_nodes = NULL;
|
||||||
|
|
||||||
|
queue = NULL;
|
||||||
|
_dump_stats_to_queue(&queue);
|
||||||
|
|
||||||
|
*doc = xmlNewDoc("1.0");
|
||||||
|
node = xmlNewDocNode(*doc, NULL, "icestats", NULL);
|
||||||
|
xmlDocSetRootElement(*doc, node);
|
||||||
|
|
||||||
|
|
||||||
|
event = _get_event_from_queue(&queue);
|
||||||
|
while (event) {
|
||||||
|
if (event->source == NULL) {
|
||||||
|
xmlNewChild(node, NULL, event->name, event->value);
|
||||||
|
} else {
|
||||||
|
srcnode = _find_xml_node(event->source, &src_nodes, node);
|
||||||
|
xmlNewChild(srcnode, NULL, event->name, event->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
_free_event(event);
|
||||||
|
event = _get_event_from_queue(&queue);
|
||||||
|
}
|
||||||
|
}
|
||||||
void stats_sendxml(client_t *client)
|
void stats_sendxml(client_t *client)
|
||||||
{
|
{
|
||||||
int bytes;
|
int bytes;
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "httpp.h"
|
#include "httpp.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
#include <libxml/xmlmemory.h>
|
||||||
|
#include <libxml/parser.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct _stats_connection_tag
|
typedef struct _stats_connection_tag
|
||||||
{
|
{
|
||||||
@ -70,7 +74,9 @@ void stats_event_dec(char *source, char *name);
|
|||||||
void *stats_connection(void *arg);
|
void *stats_connection(void *arg);
|
||||||
void *stats_callback(void *arg);
|
void *stats_callback(void *arg);
|
||||||
|
|
||||||
|
void stats_transform_xslt(client_t *client, char *xslpath);
|
||||||
void stats_sendxml(client_t *client);
|
void stats_sendxml(client_t *client);
|
||||||
|
void stats_get_xml(xmlDocPtr *doc);
|
||||||
|
|
||||||
#endif /* __STATS_H__ */
|
#endif /* __STATS_H__ */
|
||||||
|
|
||||||
|
@ -115,11 +115,6 @@ void thread_initialize(void)
|
|||||||
{
|
{
|
||||||
thread_t *thread;
|
thread_t *thread;
|
||||||
|
|
||||||
/* this must be called to init pthreads-win32 */
|
|
||||||
#ifdef _WIN32
|
|
||||||
ptw32_processInitialize();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* set up logging */
|
/* set up logging */
|
||||||
|
|
||||||
log_initialize();
|
log_initialize();
|
||||||
@ -129,7 +124,7 @@ void thread_initialize(void)
|
|||||||
log_set_level(_logid, THREAD_DEBUG);
|
log_set_level(_logid, THREAD_DEBUG);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* create all the interal mutexes, and initialize the mutex tree */
|
/* create all the internal mutexes, and initialize the mutex tree */
|
||||||
|
|
||||||
_mutextree = avl_tree_new(_compare_mutexes, NULL);
|
_mutextree = avl_tree_new(_compare_mutexes, NULL);
|
||||||
|
|
||||||
|
49
src/util.c
49
src/util.c
@ -1,4 +1,6 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
@ -10,12 +12,17 @@
|
|||||||
#else
|
#else
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#define strcasecmp stricmp
|
||||||
|
#define strncasecmp strnicmp
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "sock.h"
|
#include "sock.h"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
/* Abstract out an interface to use either poll or select depending on which
|
/* Abstract out an interface to use either poll or select depending on which
|
||||||
* is available (poll is preferred) to watch a single fd.
|
* is available (poll is preferred) to watch a single fd.
|
||||||
@ -85,6 +92,46 @@ int util_read_header(int sock, char *buff, unsigned long len)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int util_get_full_path(char *uri, char *fullPath, int fullPathLen) {
|
||||||
|
int ret = 0;
|
||||||
|
if (uri) {
|
||||||
|
memset(fullPath, '\000', fullPathLen);
|
||||||
|
snprintf(fullPath, fullPathLen-1, "%s%s%s", config_get_config()->webroot_dir, PATH_SEPARATOR, uri);
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int util_check_valid_extension(char *uri) {
|
||||||
|
int ret = 0;
|
||||||
|
char *p2;
|
||||||
|
|
||||||
|
if (uri) {
|
||||||
|
p2 = strrchr(uri, '.');
|
||||||
|
if (p2) {
|
||||||
|
p2++;
|
||||||
|
if (strncmp(p2, "xsl", strlen("xsl")) == 0) {
|
||||||
|
/* Build the full path for the request, concatenating the webroot from the config.
|
||||||
|
** Here would be also a good time to prevent accesses like '../../../../etc/passwd' or somesuch.
|
||||||
|
*/
|
||||||
|
ret = XSLT_CONTENT;
|
||||||
|
}
|
||||||
|
if (strncmp(p2, "htm", strlen("htm")) == 0) {
|
||||||
|
/* Build the full path for the request, concatenating the webroot from the config.
|
||||||
|
** Here would be also a good time to prevent accesses like '../../../../etc/passwd' or somesuch.
|
||||||
|
*/
|
||||||
|
ret = HTML_CONTENT;
|
||||||
|
}
|
||||||
|
if (strncmp(p2, "html", strlen("html")) == 0) {
|
||||||
|
/* Build the full path for the request, concatenating the webroot from the config.
|
||||||
|
** Here would be also a good time to prevent accesses like '../../../../etc/passwd' or somesuch.
|
||||||
|
*/
|
||||||
|
ret = HTML_CONTENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
#ifndef __UTIL_H__
|
#ifndef __UTIL_H__
|
||||||
#define __UTIL_H__
|
#define __UTIL_H__
|
||||||
|
|
||||||
|
#define XSLT_CONTENT 1
|
||||||
|
#define HTML_CONTENT 2
|
||||||
|
|
||||||
int util_timed_wait_for_fd(int fd, int timeout);
|
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_check_valid_extension(char *uri);
|
||||||
|
|
||||||
#endif /* __UTIL_H__ */
|
#endif /* __UTIL_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user