mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-11-03 04:17:17 -05:00
bump version. the most significant things are the stats thread removal and a theora fix.
svn path=/icecast/branches/kh/icecast/; revision=15145
This commit is contained in:
parent
f3e87bfdc3
commit
386a554a72
10
NEWS
10
NEWS
@ -15,6 +15,16 @@ Feature differences from SVN trunk
|
||||
any extra tags are show in the conf/icecast.xml.dist file
|
||||
|
||||
|
||||
2.3.2-kh1
|
||||
. remove stats thread. Stats clients still have their own thread and queue.
|
||||
. fix low bandwidth theora stream problem.
|
||||
. failing on-demand relays were not being recovered as they should of.
|
||||
. encode xml entity data for clients useragent/username
|
||||
. reduce memory usage in avl nodes, seems to benefit win32 more because of the
|
||||
unused lock handling
|
||||
. minor patch for kate detection applied. ogg.k.ogg.k
|
||||
. minor type cleanup for off_t in fserve
|
||||
|
||||
2.3-kh34
|
||||
. Added Kate/Skeleton codec handling within Ogg streams. patch by ogg.k.ogg.k
|
||||
. small changes for stream directory handling, mostly for error cases.
|
||||
|
@ -95,7 +95,7 @@
|
||||
#define PACKAGE_NAME "Icecast"
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "2.3-kh34"
|
||||
#define VERSION "2.3.2-kh1"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION VERSION
|
||||
@ -139,6 +139,8 @@ typedef unsigned int socklen_t;
|
||||
#define fseeko fseek
|
||||
#define PRIdMAX "ld"
|
||||
#define SCNdMAX "ld"
|
||||
#define SCN_OFF_T "ld"
|
||||
#define PRI_OFF_T "ld"
|
||||
|
||||
#define PRId64 "I64d"
|
||||
#define PRIu64 "I64u"
|
||||
@ -157,3 +159,6 @@ typedef unsigned int socklen_t;
|
||||
|
||||
#define sock_t SOCKET
|
||||
|
||||
/* time format for strftime */
|
||||
#define ICECAST_TIME_FMT "%a, %d %b %Y %H:%M:%S"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
AC_INIT([Icecast], [2.3-kh34], [karl@xiph.org])
|
||||
AC_INIT([Icecast], [2.3.2-kh1], [karl@xiph.org])
|
||||
|
||||
AC_PREREQ(2.59)
|
||||
AC_CONFIG_SRCDIR(src/main.c)
|
||||
@ -135,6 +135,7 @@ XIPH_PATH_OPENSSL([
|
||||
|
||||
ICECAST_OPTIONAL="$ICECAST_OPTIONAL auth_cmd.o"
|
||||
AC_DEFINE([MIMETYPESFILE],"/etc/mime.types", [Default location of mime types file])
|
||||
AC_DEFINE([ICECAST_TIME_FMT],["%a, %d %b %Y %H:%M:%S %z"], [time format for strftime])
|
||||
|
||||
dnl Make substitutions
|
||||
|
||||
|
13
src/admin.c
13
src/admin.c
@ -632,7 +632,12 @@ static void add_listener_node (xmlNodePtr srcnode, client_t *listener)
|
||||
xmlNewChild (node, NULL, XMLSTR("ip"), XMLSTR(listener->con->ip));
|
||||
|
||||
useragent = httpp_getvar (listener->parser, "user-agent");
|
||||
xmlNewChild (node, NULL, XMLSTR("useragent"), XMLSTR(useragent));
|
||||
if (useragent)
|
||||
{
|
||||
xmlChar *str = xmlEncodeEntitiesReentrant (srcnode->doc, XMLSTR(useragent));
|
||||
xmlNewChild (node, NULL, XMLSTR("useragent"), str);
|
||||
xmlFree (str);
|
||||
}
|
||||
|
||||
snprintf (buf, sizeof (buf), "%u", listener->lag);
|
||||
xmlNewChild (node, NULL, XMLSTR("lag"), XMLSTR(buf));
|
||||
@ -641,7 +646,11 @@ static void add_listener_node (xmlNodePtr srcnode, client_t *listener)
|
||||
(unsigned long)(global.time - listener->con->con_time));
|
||||
xmlNewChild (node, NULL, XMLSTR("connected"), XMLSTR(buf));
|
||||
if (listener->username)
|
||||
xmlNewChild (node, NULL, XMLSTR("username"), XMLSTR(listener->username));
|
||||
{
|
||||
xmlChar *str = xmlEncodeEntitiesReentrant (srcnode->doc, XMLSTR(listener->username));
|
||||
xmlNewChild (node, NULL, XMLSTR("username"), str);
|
||||
xmlFree (str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1120,8 +1120,6 @@ void source_startup (client_t *client, const char *uri, int auth_style)
|
||||
|
||||
static void _handle_stats_request (client_t *client, char *uri)
|
||||
{
|
||||
stats_event_inc(NULL, "stats_connections");
|
||||
|
||||
if (connection_check_admin_pass (client->parser) == 0)
|
||||
{
|
||||
client_send_401 (client, NULL);
|
||||
|
@ -209,7 +209,7 @@ ogg_codec_t *initial_kate_page (format_plugin_t *plugin, ogg_page *page)
|
||||
}
|
||||
#else
|
||||
/* we don't have libkate, so we examine the packet magic by hand */
|
||||
if ((packet.bytes<9) || memcmp(packet.packet, "\x80kate\0\0\0\0", 9))
|
||||
if ((packet.bytes<8) || memcmp(packet.packet, "\x80kate\0\0\0", 8))
|
||||
{
|
||||
ogg_stream_clear (&codec->os);
|
||||
free (kate_codec);
|
||||
|
@ -124,12 +124,6 @@ static refbuf_t *process_theora_page (ogg_state_t *ogg_info, ogg_codec_t *codec,
|
||||
refbuf = make_refbuf_with_page (codec, page);
|
||||
/* DEBUG3 ("refbuf %p has pageno %ld, %llu", refbuf, ogg_page_pageno (page), (uint64_t)granulepos); */
|
||||
|
||||
if (has_keyframe && codec->possible_start)
|
||||
{
|
||||
codec->possible_start->sync_point = 1;
|
||||
refbuf_release (codec->possible_start);
|
||||
codec->possible_start = NULL;
|
||||
}
|
||||
if (granulepos != theora->prev_granulepos || granulepos == 0)
|
||||
{
|
||||
if (codec->possible_start)
|
||||
@ -138,6 +132,12 @@ static refbuf_t *process_theora_page (ogg_state_t *ogg_info, ogg_codec_t *codec,
|
||||
codec->possible_start = refbuf;
|
||||
}
|
||||
theora->prev_granulepos = granulepos;
|
||||
if (has_keyframe && codec->possible_start)
|
||||
{
|
||||
codec->possible_start->sync_point = 1;
|
||||
refbuf_release (codec->possible_start);
|
||||
codec->possible_start = NULL;
|
||||
}
|
||||
|
||||
return refbuf;
|
||||
}
|
||||
|
14
src/fserve.c
14
src/fserve.c
@ -31,6 +31,8 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#define SCN_OFF_T SCNdMAX
|
||||
#define PRI_OFF_T PRIdMAX
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
@ -546,7 +548,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
|
||||
{
|
||||
ret = 0;
|
||||
if (strncasecmp (range, "bytes=", 6) == 0)
|
||||
ret = sscanf (range+6, "%" SCNdMAX "-", &rangenumber);
|
||||
ret = sscanf (range+6, "%" SCN_OFF_T "-", &rangenumber);
|
||||
|
||||
if (ret == 1 && rangenumber>=0 && rangenumber < content_length)
|
||||
{
|
||||
@ -576,10 +578,10 @@ int fserve_client_create (client_t *httpclient, const char *path)
|
||||
"HTTP/1.1 206 Partial Content\r\n"
|
||||
"Date: %s\r\n"
|
||||
"Accept-Ranges: bytes\r\n"
|
||||
"Content-Length: %" PRIdMAX "\r\n"
|
||||
"Content-Range: bytes %" PRIdMAX
|
||||
"-%" PRIdMAX
|
||||
"/%" PRIdMAX "\r\n"
|
||||
"Content-Length: %" PRI_OFF_T "\r\n"
|
||||
"Content-Range: bytes %" PRI_OFF_T
|
||||
"-%" PRI_OFF_T
|
||||
"/%" PRI_OFF_T "\r\n"
|
||||
"Content-Type: %s\r\n\r\n",
|
||||
currenttime,
|
||||
new_content_len,
|
||||
@ -607,7 +609,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Accept-Ranges: bytes\r\n"
|
||||
"Content-Type: %s\r\n"
|
||||
"Content-Length: %" PRIdMAX "\r\n"
|
||||
"Content-Length: %" PRI_OFF_T "\r\n"
|
||||
"\r\n",
|
||||
type,
|
||||
content_length);
|
||||
|
@ -504,6 +504,7 @@ static void *start_relay_stream (void *arg)
|
||||
thread_mutex_unlock (&src->lock);
|
||||
|
||||
/* cleanup relay, but prevent this relay from starting up again too soon */
|
||||
relay->source->on_demand = 0;
|
||||
relay->start = global.time + relay->interval;
|
||||
relay->cleanup = 1;
|
||||
|
||||
@ -1094,6 +1095,7 @@ static void *_slave_thread(void *arg)
|
||||
}
|
||||
/* trigger any YP processing */
|
||||
yp_thread_startup();
|
||||
stats_global_calc();
|
||||
}
|
||||
connection_thread_shutdown();
|
||||
INFO0 ("shutting down current relays");
|
||||
|
307
src/stats.c
307
src/stats.c
@ -44,7 +44,8 @@
|
||||
#if !defined HAVE_ATOLL && defined HAVE_STRTOLL
|
||||
#define atoll(nptr) strtoll(nptr, (char **)NULL, 10)
|
||||
#endif
|
||||
static void stats_global_calc (void);
|
||||
|
||||
#define VAL_BUFSIZE 20
|
||||
|
||||
#define STATS_EVENT_SET 0
|
||||
#define STATS_EVENT_INC 1
|
||||
@ -54,6 +55,31 @@ static void stats_global_calc (void);
|
||||
#define STATS_EVENT_REMOVE 5
|
||||
#define STATS_EVENT_HIDDEN 6
|
||||
|
||||
typedef struct _stats_node_tag
|
||||
{
|
||||
char *name;
|
||||
char *value;
|
||||
int hidden;
|
||||
} stats_node_t;
|
||||
|
||||
typedef struct _stats_event_tag
|
||||
{
|
||||
char *source;
|
||||
char *name;
|
||||
char *value;
|
||||
int hidden;
|
||||
int action;
|
||||
|
||||
struct _stats_event_tag *next;
|
||||
} stats_event_t;
|
||||
|
||||
typedef struct _stats_source_tag
|
||||
{
|
||||
char *source;
|
||||
int hidden;
|
||||
avl_tree *stats_tree;
|
||||
} stats_source_t;
|
||||
|
||||
typedef struct _event_queue_tag
|
||||
{
|
||||
volatile stats_event_t *head;
|
||||
@ -73,19 +99,14 @@ typedef struct _event_listener_tag
|
||||
} event_listener_t;
|
||||
|
||||
static volatile int _stats_running = 0;
|
||||
static thread_type *_stats_thread_id;
|
||||
static volatile int _stats_threads = 0;
|
||||
|
||||
static stats_t _stats;
|
||||
static mutex_t _stats_mutex;
|
||||
|
||||
static event_queue_t _global_event_queue;
|
||||
spin_t _global_event_mutex;
|
||||
|
||||
static volatile event_listener_t *_event_listeners;
|
||||
|
||||
|
||||
static void *_stats_thread(void *arg);
|
||||
static int _compare_stats(void *a, void *b, void *arg);
|
||||
static int _compare_source_stats(void *a, void *b, void *arg);
|
||||
static int _free_stats(void *key);
|
||||
@ -95,34 +116,21 @@ static stats_node_t *_find_node(avl_tree *tree, const char *name);
|
||||
static stats_source_t *_find_source(avl_tree *tree, const char *source);
|
||||
static void _free_event(stats_event_t *event);
|
||||
static stats_event_t *_get_event_from_queue (event_queue_t *queue);
|
||||
static void process_event (stats_event_t *event);
|
||||
|
||||
|
||||
/* simple helper function for creating an event */
|
||||
static stats_event_t *build_event (const char *source, const char *name, const char *value)
|
||||
static void build_event (stats_event_t *event, const char *source, const char *name, const char *value)
|
||||
{
|
||||
stats_event_t *event;
|
||||
|
||||
event = (stats_event_t *)calloc(1, sizeof(stats_event_t));
|
||||
if (event)
|
||||
{
|
||||
if (source)
|
||||
event->source = (char *)strdup(source);
|
||||
if (name)
|
||||
event->name = (char *)strdup(name);
|
||||
if (value)
|
||||
event->value = (char *)strdup(value);
|
||||
else
|
||||
event->action = STATS_EVENT_REMOVE;
|
||||
}
|
||||
return event;
|
||||
event->source = (char *)source;
|
||||
event->name = (char *)name;
|
||||
event->value = (char *)value;
|
||||
if (value)
|
||||
event->action = 0;
|
||||
else
|
||||
event->action = STATS_EVENT_REMOVE;
|
||||
}
|
||||
|
||||
static void queue_global_event (stats_event_t *event)
|
||||
{
|
||||
thread_spin_lock(&_global_event_mutex);
|
||||
_add_event_to_queue (event, &_global_event_queue);
|
||||
thread_spin_unlock(&_global_event_mutex);
|
||||
}
|
||||
|
||||
void stats_initialize(void)
|
||||
{
|
||||
@ -135,13 +143,26 @@ void stats_initialize(void)
|
||||
/* set up global mutex */
|
||||
thread_mutex_create("stats", &_stats_mutex);
|
||||
|
||||
/* set up stats queues */
|
||||
event_queue_init (&_global_event_queue);
|
||||
thread_spin_create("stats_global_event", &_global_event_mutex);
|
||||
|
||||
/* fire off the stats thread */
|
||||
_stats_running = 1;
|
||||
_stats_thread_id = thread_create("Stats Thread", _stats_thread, NULL, THREAD_ATTACHED);
|
||||
|
||||
stats_event_time (NULL, "server_start");
|
||||
|
||||
/* global currently active stats */
|
||||
stats_event (NULL, "clients", "0");
|
||||
stats_event (NULL, "connections", "0");
|
||||
stats_event (NULL, "sources", "0");
|
||||
stats_event (NULL, "stats", "0");
|
||||
stats_event (NULL, "listeners", "0");
|
||||
|
||||
/* global accumulating stats */
|
||||
stats_event (NULL, "client_connections", "0");
|
||||
stats_event (NULL, "source_client_connections", "0");
|
||||
stats_event (NULL, "source_relay_connections", "0");
|
||||
stats_event (NULL, "source_total_connections", "0");
|
||||
stats_event (NULL, "stats_connections", "0");
|
||||
stats_event (NULL, "listener_connections", "0");
|
||||
stats_event (NULL, "outgoing_kbitrate", "0");
|
||||
}
|
||||
|
||||
void stats_shutdown(void)
|
||||
@ -153,7 +174,6 @@ void stats_shutdown(void)
|
||||
|
||||
/* wait for thread to exit */
|
||||
_stats_running = 0;
|
||||
thread_join(_stats_thread_id);
|
||||
|
||||
/* wait for other threads to shut down */
|
||||
do {
|
||||
@ -166,25 +186,9 @@ void stats_shutdown(void)
|
||||
|
||||
/* free the queues */
|
||||
|
||||
/* destroy the queue mutexes */
|
||||
thread_spin_destroy(&_global_event_mutex);
|
||||
|
||||
thread_mutex_destroy(&_stats_mutex);
|
||||
avl_tree_free(_stats.source_tree, _free_source_stats);
|
||||
avl_tree_free(_stats.global_tree, _free_stats);
|
||||
|
||||
while (1)
|
||||
{
|
||||
stats_event_t *event = _get_event_from_queue (&_global_event_queue);
|
||||
if (event == NULL) break;
|
||||
if(event->source)
|
||||
free(event->source);
|
||||
if(event->value)
|
||||
free(event->value);
|
||||
if(event->name)
|
||||
free(event->name);
|
||||
free(event);
|
||||
}
|
||||
}
|
||||
|
||||
stats_t *stats_get_stats(void)
|
||||
@ -203,16 +207,15 @@ stats_t *stats_get_stats(void)
|
||||
/* simple name=tag stat create/update */
|
||||
void stats_event(const char *source, const char *name, const char *value)
|
||||
{
|
||||
stats_event_t *event;
|
||||
stats_event_t event;
|
||||
|
||||
if (value && xmlCheckUTF8 ((unsigned char *)value) == 0)
|
||||
{
|
||||
WARN2 ("seen non-UTF8 data, probably incorrect metadata (%s, %s)", name, value);
|
||||
return;
|
||||
}
|
||||
event = build_event (source, name, value);
|
||||
if (event)
|
||||
queue_global_event (event);
|
||||
build_event (&event, source, name, (char *)value);
|
||||
process_event (&event);
|
||||
}
|
||||
|
||||
|
||||
@ -258,17 +261,14 @@ void stats_event_conv(const char *mount, const char *name, const char *value, co
|
||||
* source stats tree. */
|
||||
void stats_event_hidden (const char *source, const char *name, int hidden)
|
||||
{
|
||||
stats_event_t *event;
|
||||
const char *str = NULL;
|
||||
stats_event_t event;
|
||||
|
||||
if (hidden)
|
||||
str = "";
|
||||
event = build_event (source, name, str);
|
||||
if (event)
|
||||
{
|
||||
event->action = STATS_EVENT_HIDDEN;
|
||||
queue_global_event (event);
|
||||
}
|
||||
build_event (&event, source, name, NULL);
|
||||
event.action = STATS_EVENT_HIDDEN;
|
||||
process_event (&event);
|
||||
}
|
||||
|
||||
/* printf style formatting for stat create/update */
|
||||
@ -325,51 +325,46 @@ char *stats_get_value(const char *source, const char *name)
|
||||
/* increase the value in the provided stat by 1 */
|
||||
void stats_event_inc(const char *source, const char *name)
|
||||
{
|
||||
stats_event_t *event = build_event (source, name, NULL);
|
||||
stats_event_t event;
|
||||
char buffer[VAL_BUFSIZE];
|
||||
build_event (&event, source, name, buffer);
|
||||
/* DEBUG2("%s on %s", name, source==NULL?"global":source); */
|
||||
if (event)
|
||||
{
|
||||
event->action = STATS_EVENT_INC;
|
||||
queue_global_event (event);
|
||||
}
|
||||
event.action = STATS_EVENT_INC;
|
||||
process_event (&event);
|
||||
}
|
||||
|
||||
void stats_event_add(const char *source, const char *name, unsigned long value)
|
||||
{
|
||||
stats_event_t *event = build_event (source, name, NULL);
|
||||
stats_event_t event;
|
||||
char buffer [VAL_BUFSIZE];
|
||||
|
||||
build_event (&event, source, name, buffer);
|
||||
snprintf (buffer, VAL_BUFSIZE, "%ld", value);
|
||||
event.action = STATS_EVENT_ADD;
|
||||
/* DEBUG2("%s on %s", name, source==NULL?"global":source); */
|
||||
if (event)
|
||||
{
|
||||
event->value = malloc (16);
|
||||
snprintf (event->value, 16, "%ld", value);
|
||||
event->action = STATS_EVENT_ADD;
|
||||
queue_global_event (event);
|
||||
}
|
||||
process_event (&event);
|
||||
}
|
||||
|
||||
void stats_event_sub(const char *source, const char *name, unsigned long value)
|
||||
{
|
||||
stats_event_t *event = build_event (source, name, NULL);
|
||||
stats_event_t event;
|
||||
char buffer[VAL_BUFSIZE];
|
||||
build_event (&event, source, name, buffer);
|
||||
/* DEBUG2("%s on %s", name, source==NULL?"global":source); */
|
||||
if (event)
|
||||
{
|
||||
event->value = malloc (16);
|
||||
snprintf (event->value, 16, "%ld", value);
|
||||
event->action = STATS_EVENT_SUB;
|
||||
queue_global_event (event);
|
||||
}
|
||||
snprintf (buffer, VAL_BUFSIZE, "%ld", value);
|
||||
event.action = STATS_EVENT_SUB;
|
||||
process_event (&event);
|
||||
}
|
||||
|
||||
/* decrease the value in the provided stat by 1 */
|
||||
void stats_event_dec(const char *source, const char *name)
|
||||
{
|
||||
stats_event_t event;
|
||||
char buffer[VAL_BUFSIZE];
|
||||
/* DEBUG2("%s on %s", name, source==NULL?"global":source); */
|
||||
stats_event_t *event = build_event (source, name, NULL);
|
||||
if (event)
|
||||
{
|
||||
event->action = STATS_EVENT_DEC;
|
||||
queue_global_event (event);
|
||||
}
|
||||
build_event (&event, source, name, buffer);
|
||||
event.action = STATS_EVENT_DEC;
|
||||
process_event (&event);
|
||||
}
|
||||
|
||||
/* note: you must call this function only when you have exclusive access
|
||||
@ -448,8 +443,8 @@ static stats_event_t *_copy_event(stats_event_t *event)
|
||||
/* helper to apply specialised changes to a stats node */
|
||||
static void modify_node_event (stats_node_t *node, stats_event_t *event)
|
||||
{
|
||||
char *str;
|
||||
|
||||
if (node == NULL || event == NULL)
|
||||
return;
|
||||
if (event->action == STATS_EVENT_HIDDEN)
|
||||
{
|
||||
if (event->value)
|
||||
@ -479,15 +474,10 @@ static void modify_node_event (stats_node_t *node, stats_event_t *event)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
str = malloc (20);
|
||||
snprintf (str, 20, "%" PRId64, value);
|
||||
free (event->value);
|
||||
event->value = strdup (str);
|
||||
snprintf (event->value, VAL_BUFSIZE, "%" PRId64, value);
|
||||
}
|
||||
else
|
||||
str = (char *)strdup (event->value);
|
||||
free (node->value);
|
||||
node->value = str;
|
||||
node->value = strdup (event->value);
|
||||
}
|
||||
|
||||
|
||||
@ -604,7 +594,7 @@ void stats_event_time (const char *mount, const char *name)
|
||||
char buffer[100];
|
||||
|
||||
localtime_r (&now, &local);
|
||||
strftime (buffer, sizeof (buffer), "%a, %d %b %Y %H:%M:%S %z", &local);
|
||||
strftime (buffer, sizeof (buffer), ICECAST_TIME_FMT, &local);
|
||||
stats_event (mount, name, buffer);
|
||||
}
|
||||
|
||||
@ -640,64 +630,26 @@ void stats_global (ice_config_t *config)
|
||||
stats_event (NULL, "admin", config->admin);
|
||||
}
|
||||
|
||||
|
||||
static void *_stats_thread(void *arg)
|
||||
static void process_event_unlocked (stats_event_t *event)
|
||||
{
|
||||
stats_event_t *event;
|
||||
/* check if we are dealing with a global or source event */
|
||||
if (event->source == NULL)
|
||||
process_global_event (event);
|
||||
else
|
||||
process_source_event (event);
|
||||
|
||||
stats_event_time (NULL, "server_start");
|
||||
/* now we have an event that's been processed into the running stats */
|
||||
/* this event should get copied to event listeners' queues */
|
||||
stats_listener_send (event);
|
||||
}
|
||||
|
||||
/* global currently active stats */
|
||||
stats_event (NULL, "clients", "0");
|
||||
stats_event (NULL, "connections", "0");
|
||||
stats_event (NULL, "sources", "0");
|
||||
stats_event (NULL, "stats", "0");
|
||||
stats_event (NULL, "listeners", "0");
|
||||
|
||||
/* global accumulating stats */
|
||||
stats_event (NULL, "client_connections", "0");
|
||||
stats_event (NULL, "source_client_connections", "0");
|
||||
stats_event (NULL, "source_relay_connections", "0");
|
||||
stats_event (NULL, "source_total_connections", "0");
|
||||
stats_event (NULL, "stats_connections", "0");
|
||||
stats_event (NULL, "listener_connections", "0");
|
||||
stats_event (NULL, "outgoing_kbitrate", "0");
|
||||
|
||||
INFO0 ("stats thread started");
|
||||
while (_stats_running) {
|
||||
if (_global_event_queue.head != NULL) {
|
||||
/* grab the next event from the queue */
|
||||
thread_spin_lock(&_global_event_mutex);
|
||||
event = _get_event_from_queue (&_global_event_queue);
|
||||
thread_spin_unlock(&_global_event_mutex);
|
||||
|
||||
if (event == NULL)
|
||||
continue;
|
||||
event->next = NULL;
|
||||
|
||||
thread_mutex_lock(&_stats_mutex);
|
||||
|
||||
/* check if we are dealing with a global or source event */
|
||||
if (event->source == NULL)
|
||||
process_global_event (event);
|
||||
else
|
||||
process_source_event (event);
|
||||
|
||||
/* now we have an event that's been processed into the running stats */
|
||||
/* this event should get copied to event listeners' queues */
|
||||
stats_listener_send (event);
|
||||
|
||||
/* now we need to destroy the event */
|
||||
_free_event(event);
|
||||
|
||||
thread_mutex_unlock(&_stats_mutex);
|
||||
continue;
|
||||
}
|
||||
thread_sleep(500000);
|
||||
stats_global_calc();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
static void process_event (stats_event_t *event)
|
||||
{
|
||||
if (event == NULL)
|
||||
return;
|
||||
thread_mutex_lock (&_stats_mutex);
|
||||
process_event_unlocked (event);
|
||||
thread_mutex_unlock (&_stats_mutex);
|
||||
}
|
||||
|
||||
/* you must have the _stats_mutex locked here */
|
||||
@ -705,6 +657,9 @@ static void _unregister_listener(event_listener_t *listener)
|
||||
{
|
||||
event_listener_t **prev = (event_listener_t **)&_event_listeners,
|
||||
*current = *prev;
|
||||
stats_event_t stats_count, *event;
|
||||
char buffer [VAL_BUFSIZE];
|
||||
|
||||
while (current)
|
||||
{
|
||||
if (current == listener)
|
||||
@ -715,6 +670,15 @@ static void _unregister_listener(event_listener_t *listener)
|
||||
prev = ¤t->next;
|
||||
current = *prev;
|
||||
}
|
||||
|
||||
/* remove this listener before sending this change */
|
||||
build_event (&stats_count, NULL, "stats_connections", buffer);
|
||||
stats_count.action = STATS_EVENT_DEC;
|
||||
process_event_unlocked (&stats_count);
|
||||
|
||||
/* flush any extra that sneaked on at the last moment */
|
||||
while ((event = _get_event_from_queue (&listener->queue)) != NULL)
|
||||
_free_event (event);
|
||||
}
|
||||
|
||||
|
||||
@ -823,8 +787,12 @@ static void _register_listener (event_listener_t *listener)
|
||||
avl_node *node2;
|
||||
stats_event_t *event;
|
||||
stats_source_t *source;
|
||||
stats_event_t stats_count;
|
||||
char buffer[20];
|
||||
|
||||
thread_mutex_lock(&_stats_mutex);
|
||||
build_event (&stats_count, NULL, "stats_connections", buffer);
|
||||
stats_count.action = STATS_EVENT_INC;
|
||||
process_event_unlocked (&stats_count);
|
||||
|
||||
/* first we fill our queue with the current stats */
|
||||
|
||||
@ -855,11 +823,8 @@ static void _register_listener (event_listener_t *listener)
|
||||
/* now we register to receive future event notices */
|
||||
listener->next = (event_listener_t *)_event_listeners;
|
||||
_event_listeners = listener;
|
||||
|
||||
thread_mutex_unlock(&_stats_mutex);
|
||||
}
|
||||
|
||||
|
||||
static void check_uri (event_listener_t *listener, client_t *client)
|
||||
{
|
||||
const char *mount = httpp_getvar (client->parser, HTTPP_VAR_URI);
|
||||
@ -883,12 +848,10 @@ void *stats_connection(void *arg)
|
||||
/* increment the thread count */
|
||||
thread_mutex_lock(&_stats_mutex);
|
||||
_stats_threads++;
|
||||
stats_event_args (NULL, "stats", "%d", _stats_threads);
|
||||
thread_mutex_unlock(&_stats_mutex);
|
||||
|
||||
thread_mutex_create("stats local event", &listener.mutex);
|
||||
|
||||
_register_listener (&listener);
|
||||
thread_mutex_unlock(&_stats_mutex);
|
||||
|
||||
while (_stats_running) {
|
||||
thread_mutex_lock (&listener.mutex);
|
||||
@ -908,7 +871,6 @@ void *stats_connection(void *arg)
|
||||
thread_mutex_lock(&_stats_mutex);
|
||||
_unregister_listener (&listener);
|
||||
_stats_threads--;
|
||||
stats_event_args (NULL, "stats", "%d", _stats_threads);
|
||||
thread_mutex_unlock(&_stats_mutex);
|
||||
|
||||
thread_mutex_destroy (&listener.mutex);
|
||||
@ -939,7 +901,7 @@ typedef struct _source_xml_tag {
|
||||
struct _source_xml_tag *next;
|
||||
} source_xml_t;
|
||||
|
||||
static xmlNodePtr _find_xml_node(char *mount, source_xml_t **list, xmlNodePtr root)
|
||||
static xmlNodePtr _find_xml_node(const char *mount, source_xml_t **list, xmlNodePtr root)
|
||||
{
|
||||
source_xml_t *node, *node2;
|
||||
int found = 0;
|
||||
@ -1185,30 +1147,21 @@ void stats_clear_virtual_mounts (void)
|
||||
}
|
||||
|
||||
|
||||
static void stats_global_calc (void)
|
||||
void stats_global_calc (void)
|
||||
{
|
||||
stats_event_t event;
|
||||
stats_node_t *node;
|
||||
char buffer [20];
|
||||
char buffer [VAL_BUFSIZE];
|
||||
static time_t next_update = 0;
|
||||
|
||||
if (global.time < next_update)
|
||||
return;
|
||||
next_update = global.time + 1;
|
||||
event.source = NULL;
|
||||
event.name = "outgoing_kbitrate";
|
||||
event.value = buffer;
|
||||
event.action = STATS_EVENT_SET;
|
||||
build_event (&event, NULL, "outgoing_kbitrate", buffer);
|
||||
|
||||
thread_mutex_lock (&_stats_mutex);
|
||||
node = _find_node(_stats.global_tree, event.name);
|
||||
if (node)
|
||||
{
|
||||
snprintf (buffer, sizeof(buffer), "%" PRIu64,
|
||||
snprintf (buffer, sizeof(buffer), "%" PRIu64,
|
||||
(int64_t)(global_getrate_avg (global.out_bitrate) * 8 / 1000.0 + 0.5));
|
||||
modify_node_event (node, &event);
|
||||
stats_listener_send (&event);
|
||||
}
|
||||
process_event_unlocked (&event);
|
||||
thread_mutex_unlock (&_stats_mutex);
|
||||
}
|
||||
|
||||
|
26
src/stats.h
26
src/stats.h
@ -22,31 +22,6 @@
|
||||
#include <libxml/tree.h>
|
||||
|
||||
|
||||
typedef struct _stats_node_tag
|
||||
{
|
||||
char *name;
|
||||
char *value;
|
||||
int hidden;
|
||||
} stats_node_t;
|
||||
|
||||
typedef struct _stats_event_tag
|
||||
{
|
||||
char *source;
|
||||
char *name;
|
||||
char *value;
|
||||
int hidden;
|
||||
int action;
|
||||
|
||||
struct _stats_event_tag *next;
|
||||
} stats_event_t;
|
||||
|
||||
typedef struct _stats_source_tag
|
||||
{
|
||||
char *source;
|
||||
int hidden;
|
||||
avl_tree *stats_tree;
|
||||
} stats_source_t;
|
||||
|
||||
typedef struct _stats_tag
|
||||
{
|
||||
avl_tree *global_tree;
|
||||
@ -93,6 +68,7 @@ void stats_event_time (const char *mount, const char *name);
|
||||
|
||||
void *stats_connection(void *arg);
|
||||
void stats_callback (client_t *client, void *notused);
|
||||
void stats_global_calc(void);
|
||||
|
||||
void stats_transform_xslt(client_t *client, const char *uri);
|
||||
void stats_sendxml(client_t *client);
|
||||
|
@ -11,6 +11,6 @@ dist_web_DATA = status.xsl \
|
||||
server_version.xsl \
|
||||
adminbar.html \
|
||||
statusbar.html \
|
||||
admin.html \
|
||||
index.html \
|
||||
admin.html \
|
||||
index.html \
|
||||
favicon.ico
|
||||
|
12
web/admin.html
Normal file
12
web/admin.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="/style.css" />
|
||||
<title>Icecast Streaming Media Server</title>
|
||||
</head>
|
||||
|
||||
<frameset rows="170,*" border="0">
|
||||
<frame name="header" frameborder="0" scrolling="no" width="100%" src="/adminbar.html" />
|
||||
<frame name="content" frameborder="0" scrolling="auto" width="100%" src="/admin/stats.xsl" />
|
||||
</frameset>
|
||||
</html>
|
@ -12,5 +12,5 @@ EXTRA_DIST = ConfigTab.cpp ConfigTab.h Icecast2win.clw Icecast2win.cpp \
|
||||
colors.h icecast.dsp icecast.ico icecast2.iss icecast2logo2.bmp\
|
||||
resource.h running.bmp stopped.bmp TRAYNOT.h Traynot.cpp \
|
||||
icecast2_console.dsw icecast2_console.dsp credits.bmp icecast2title.bmp \
|
||||
icecastService.cpp icecastService.dsp fnmatch.h
|
||||
icecastService.cpp icecastService.dsp
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
[Setup]
|
||||
AppName=Icecast2-KH
|
||||
AppVerName=Icecast v2.3.1-kh34
|
||||
AppVerName=Icecast v2.3.2-kh1
|
||||
AppPublisherURL=http://www.icecast.org
|
||||
AppSupportURL=http://www.icecast.org
|
||||
AppUpdatesURL=http://www.icecast.org
|
||||
@ -13,7 +13,7 @@ AllowNoIcons=yes
|
||||
LicenseFile=..\COPYING
|
||||
InfoAfterFile=..\README
|
||||
OutputDir=.
|
||||
OutputBaseFilename=icecast2_win32_v2.3.1-kh34_setup
|
||||
OutputBaseFilename=icecast2_win32_v2.3.2-kh1_setup
|
||||
WizardImageFile=icecast2logo2.bmp
|
||||
WizardImageStretch=no
|
||||
; uncomment the following line if you want your installation to run on NT 3.51 too.
|
||||
|
@ -50,7 +50,8 @@ BSC32=bscmake.exe
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 theora_static_d.lib libspeex.lib ogg_static.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libcurl.lib vorbis_static.lib libxml2.lib libxslt.lib iconv.lib pthreadVSE.lib ws2_32.lib ssleay32MT.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /nodefaultlib:"libcmt.lib"
|
||||
# ADD LINK32 theora_static_d.lib libspeex.lib ogg_static.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libcurl.lib vorbis_static.lib libxml2.lib libxslt.lib iconv.lib pthreadVSE.lib ws2_32.lib winmm.lib ssleay32MT.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /nodefaultlib:"libcmt.lib"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "icecast2 console - Win32 Debug"
|
||||
|
||||
@ -74,7 +75,8 @@ BSC32=bscmake.exe
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 theora_static_d.lib libspeex.lib ogg_static.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libcurl.lib vorbis_static.lib libxml2.lib libxslt.lib iconv.lib pthreadVSE.lib ws2_32.lib ssleay32MT.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /nodefaultlib:"libcmt.lib" /nodefaultlib:"libcmtd.lib" /pdbtype:sept
|
||||
# ADD LINK32 theora_static_d.lib libspeex.lib ogg_static.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libcurl.lib vorbis_static.lib libxml2.lib libxslt.lib iconv.lib pthreadVSE.lib ws2_32.lib winmm.lib ssleay32MT.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /nodefaultlib:"libcmt.lib" /nodefaultlib:"libcmtd.lib" /pdbtype:sept
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ENDIF
|
||||
|
||||
|
@ -43,7 +43,6 @@ RSC=rc.exe
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I ".." /I "..\src" /D "NDEBUG" /D "_CONSOLE" /D "WIN32_SERVICE" /D HAVE_CONFIG_H=1 /D "WIN32" /D "_MBCS" /YX /FD /c
|
||||
# SUBTRACT CPP /Z<none>
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
@ -51,8 +50,7 @@ BSC32=bscmake.exe
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 libspeex.lib theora_static_d.lib ogg_static.lib vorbis_static.lib pthreadVSE.lib ssleay32MT.lib libcurl.lib libxml2.lib libxslt.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /machine:I386 /nodefaultlib:"libcmt.lib" /nodefaultlib:"libcmtd.lib" /nodefaultlib:"libcd.lib"
|
||||
# SUBTRACT LINK32 /debug
|
||||
# ADD LINK32 libspeex.lib theora_static_d.lib ogg_static.lib vorbis_static.lib pthreadVSE.lib ssleay32MT.lib libcurl.lib libxml2.lib libxslt.lib ws2_32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /machine:I386 /nodefaultlib:"libcmt.lib" /nodefaultlib:"libcmtd.lib" /nodefaultlib:"libcd.lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "icecastService - Win32 Debug"
|
||||
|
||||
@ -76,8 +74,8 @@ BSC32=bscmake.exe
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 vorbis_static.lib iconv.lib libspeex.lib theora_static_d.lib ogg_static_d.lib vorbis_static_d.lib pthreadVSE.lib ssleay32MT.lib libcurl.lib libxml2.lib libxslt.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /nodefaultlib:"libcd.lib" /nodefaultlib:"libcmt.lib" /out:"service_debug/icecast2service.exe" /pdbtype:sept
|
||||
# SUBTRACT LINK32 /verbose
|
||||
# ADD LINK32 vorbis_static.lib iconv.lib libspeex.lib theora_static_d.lib ogg_static_d.lib vorbis_static_d.lib pthreadVSE.lib ssleay32MT.lib libcurl.lib libxml2.lib libxslt.lib ws2_32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /nodefaultlib:"libcd.lib" /nodefaultlib:"libcmt.lib" /out:"service_debug/icecast2service.exe" /pdbtype:sept
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ENDIF
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user