1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-09-22 04:15:54 -04:00

check-in changes for kh3, bugfix for streamlist for slaves and some on-going

internal code cleanup

svn path=/icecast/branches/kh/icecast/; revision=15463
This commit is contained in:
Karl Heyes 2008-10-29 02:57:06 +00:00
parent b6dc964a29
commit f7801fb88c
15 changed files with 238 additions and 127 deletions

10
NEWS
View File

@ -15,6 +15,16 @@ Feature differences from SVN trunk
any extra tags are show in the conf/icecast.xml.dist file
2.3.2-kh3
. fixed master not informing slaves of streams bug. caused by missed setting in
the kh2 stats update
. more xml checks for badly formed xml files.
. log files can now be sections not just a single filename ie <errorlog> can
contain <name> <archive> <display> and <level>, accesslog can contain <name>
<ip> and <archive>, playlistlog can contain <name> <archive> <display>. In each
case, name is a filename, archive is a true/false setting for using timestamps
on a reopened file, display is the number of lines to show in the admin page.
2.3.2-kh2
. more stats work. Clients are now processed as needed instead of a dedicated
thread per stats client.

View File

@ -95,7 +95,7 @@
#define PACKAGE_NAME "Icecast"
/* Version number of package */
#define VERSION "2.3.2-kh2"
#define VERSION "2.3.2-kh3"
/* Define to the version of this package. */
#define PACKAGE_VERSION VERSION

View File

@ -1,4 +1,4 @@
AC_INIT([Icecast], [2.3.2-kh2], [karl@xiph.org])
AC_INIT([Icecast], [2.3.2-kh3], [karl@xiph.org])
AC_PREREQ(2.59)
AC_CONFIG_SRCDIR(src/main.c)

View File

@ -1122,7 +1122,7 @@ static void command_stats (client_t *client, const char *filename)
show_mount = httpp_get_query_param (client->parser, "mount");
stats_get_xml(&doc, STATS_ALL, show_mount);
doc = stats_get_xml (STATS_ALL, show_mount);
admin_send_response (doc, client, response, filename);
xmlFreeDoc(doc);
}

View File

@ -100,72 +100,84 @@ struct cfg_tag
*/
int config_get_bool (xmlNodePtr node, void *x)
{
char *str = (char *)xmlNodeListGetString (node->doc, node->xmlChildrenNode, 1);
if (str == NULL)
return 1;
if (strcasecmp (str, "true") == 0)
*(int*)x = 1;
else
if (strcasecmp (str, "yes") == 0)
if (xmlNodeIsText (node))
{
char *str = (char *)xmlNodeListGetString (node->doc, node->xmlChildrenNode, 1);
if (str == NULL)
return 1;
if (strcasecmp (str, "true") == 0)
*(int*)x = 1;
else
*(int*)x = strtol (str, NULL, 0)==0 ? 0 : 1;
xmlFree (str);
if (strcasecmp (str, "yes") == 0)
*(int*)x = 1;
else
*(int*)x = strtol (str, NULL, 0)==0 ? 0 : 1;
xmlFree (str);
}
return 0;
}
int config_get_str (xmlNodePtr node, void *x)
{
xmlChar *str = xmlNodeListGetString (node->doc, node->xmlChildrenNode, 1);
xmlChar *p = *(xmlChar**)x;
if (str == NULL)
return 1;
if (p)
xmlFree (p);
*(xmlChar **)x = str;
if (xmlIsBlankNode (node) == 0)
{
xmlChar *str = xmlNodeListGetString (node->doc, node->xmlChildrenNode, 1);
xmlChar *p = *(xmlChar**)x;
if (str == NULL)
return 1;
if (p)
xmlFree (p);
*(xmlChar **)x = str;
}
return 0;
}
int config_get_int (xmlNodePtr node, void *x)
{
xmlChar *str = xmlNodeListGetString (node->doc, node->xmlChildrenNode, 1);
if (str == NULL)
return 1;
*(int*)x = strtol ((char*)str, NULL, 0);
xmlFree (str);
if (xmlIsBlankNode (node) == 0)
{
xmlChar *str = xmlNodeListGetString (node->doc, node->xmlChildrenNode, 1);
if (str == NULL)
return 1;
*(int*)x = strtol ((char*)str, NULL, 0);
xmlFree (str);
}
return 0;
}
int config_get_bitrate (xmlNodePtr node, void *x)
{
xmlChar *str = xmlNodeListGetString (node->doc, node->xmlChildrenNode, 1);
int64_t *p = (int64_t*)x;
char metric = '\0';
if (xmlIsBlankNode (node) == 0)
{
xmlChar *str = xmlNodeListGetString (node->doc, node->xmlChildrenNode, 1);
int64_t *p = (int64_t*)x;
char metric = '\0';
if (str == NULL)
return 1;
sscanf ((char*)str, "%"SCNd64 "%c", p, &metric);
if (metric == 'k' || metric == 'K')
(*p) *= 1024;
if (metric == 'm' || metric == 'M')
(*p) *= 1024*1024;
xmlFree (str);
if (str == NULL)
return 1;
sscanf ((char*)str, "%"SCNd64 "%c", p, &metric);
if (metric == 'k' || metric == 'K')
(*p) *= 1024;
if (metric == 'm' || metric == 'M')
(*p) *= 1024*1024;
xmlFree (str);
}
return 0;
}
int parse_xml_tags (xmlNodePtr parent, const struct cfg_tag *args)
{
int ret = 0;
int ret = 0, seen_element = 0;
xmlNodePtr node = parent->xmlChildrenNode;
for (; node != NULL && ret == 0; node = node->next)
{
const struct cfg_tag *argp;
if (xmlIsBlankNode (node) || strcmp ((char*)node->name, "comment") == 0 ||
strcmp ((char*)node->name, "text") == 0)
if (xmlIsBlankNode (node) || node->type != XML_ELEMENT_NODE)
continue;
seen_element = 1;
argp = args;
while (argp->name)
{
@ -174,6 +186,12 @@ int parse_xml_tags (xmlNodePtr parent, const struct cfg_tag *args)
ret = argp->retrieve (node, argp->storage);
if (ret > 0)
{
if (ret == 2)
{
argp++;
ret = 0;
continue;
}
xmlParserWarning (NULL, "skipping element \"%s\" parsing \"%s\"\n", node->name, parent->name);
ret = 0;
}
@ -184,6 +202,8 @@ int parse_xml_tags (xmlNodePtr parent, const struct cfg_tag *args)
if (argp->name == NULL)
WARN2 ("unknown element \"%s\" parsing \"%s\"", node->name, parent->name);
}
if (ret == 0 && seen_element == 0)
return 2;
return ret;
}
@ -301,10 +321,10 @@ void config_clear(ice_config_t *c)
if (c->banfile) xmlFree(c->banfile);
if (c->allowfile) xmlFree (c->allowfile);
if (c->agentfile) xmlFree (c->agentfile);
if (c->playlist_log) xmlFree(c->playlist_log);
if (c->access_log) xmlFree(c->access_log);
if (c->error_log) xmlFree(c->error_log);
if (c->access_log_exclude_ext) xmlFree (c->access_log_exclude_ext);
if (c->playlist_log.name) xmlFree(c->playlist_log.name);
if (c->access_log.name) xmlFree(c->access_log.name);
if (c->error_log.name) xmlFree(c->error_log.name);
if (c->access_log.exclude_ext) xmlFree (c->access_log.exclude_ext);
if (c->shoutcast_mount) xmlFree(c->shoutcast_mount);
while ((c->listen_sock = config_clear_listener (c->listen_sock)))
@ -471,11 +491,11 @@ static void _set_defaults(ice_config_t *configuration)
configuration->log_dir = (char *)xmlCharStrdup (CONFIG_DEFAULT_LOG_DIR);
configuration->webroot_dir = (char *)xmlCharStrdup (CONFIG_DEFAULT_WEBROOT_DIR);
configuration->adminroot_dir = (char *)xmlCharStrdup (CONFIG_DEFAULT_ADMINROOT_DIR);
configuration->playlist_log = (char *)xmlCharStrdup (CONFIG_DEFAULT_PLAYLIST_LOG);
configuration->access_log = (char *)xmlCharStrdup (CONFIG_DEFAULT_ACCESS_LOG);
configuration->access_log_ip = 1;
configuration->error_log = (char *)xmlCharStrdup (CONFIG_DEFAULT_ERROR_LOG);
configuration->loglevel = CONFIG_DEFAULT_LOG_LEVEL;
configuration->playlist_log.name = (char *)xmlCharStrdup (CONFIG_DEFAULT_PLAYLIST_LOG);
configuration->access_log.name = (char *)xmlCharStrdup (CONFIG_DEFAULT_ACCESS_LOG);
configuration->access_log.log_ip = 1;
configuration->error_log.name = (char *)xmlCharStrdup (CONFIG_DEFAULT_ERROR_LOG);
configuration->error_log.level = CONFIG_DEFAULT_LOG_LEVEL;
configuration->chroot = CONFIG_DEFAULT_CHROOT;
configuration->chuid = CONFIG_DEFAULT_CHUID;
configuration->user = NULL;
@ -568,34 +588,93 @@ static int _parse_security (xmlNodePtr node, void *arg)
return 0;
}
static int _parse_logging (xmlNodePtr node, void *arg)
static int _parse_accesslog (xmlNodePtr node, void *arg)
{
ice_config_t *config = arg;
access_log *log = arg;
struct cfg_tag icecast_tags[] =
{
{ "accesslog", config_get_str, &config->access_log },
{ "accesslog_ip", config_get_bool, &config->access_log_ip },
{ "accesslog_exclude_ext",
config_get_str, &config->access_log_exclude_ext },
{ "accesslog_lines",
config_get_int, &config->access_log_lines },
{ "errorlog", config_get_str, &config->error_log },
{ "errorlog_lines", config_get_int, &config->error_log_lines },
{ "playlistlog", config_get_str, &config->playlist_log },
{ "playlistlog_lines",
config_get_int, &config->playlist_log_lines },
{ "logsize", config_get_int, &config->logsize },
{ "loglevel", config_get_int, &config->loglevel },
{ "logarchive", config_get_bool, &config->logarchive },
{ "name", config_get_str, &log->name },
{ "ip", config_get_bool, &log->log_ip },
{ "archive", config_get_bool, &log->archive },
{ "exclude_ext", config_get_str, &log->exclude_ext },
{ "display", config_get_int, &log->display },
{ NULL, NULL, NULL }
};
config->access_log_lines = 100;
config->error_log_lines = 100;
config->playlist_log_lines = 10;
return parse_xml_tags (node, icecast_tags);
}
static int _parse_errorlog (xmlNodePtr node, void *arg)
{
error_log *log = arg;
struct cfg_tag icecast_tags[] =
{
{ "name", config_get_str, &log->name },
{ "archive", config_get_bool, &log->archive },
{ "display", config_get_int, &log->display },
{ "level", config_get_int, &log->level },
{ NULL, NULL, NULL }
};
return parse_xml_tags (node, icecast_tags);
}
static int _parse_playlistlog (xmlNodePtr node, void *arg)
{
playlist_log *log = arg;
struct cfg_tag icecast_tags[] =
{
{ "name", config_get_str, &log->name },
{ "archive", config_get_bool, &log->archive },
{ "display", config_get_int, &log->display },
{ NULL, NULL, NULL }
};
return parse_xml_tags (node, icecast_tags);
}
static int _parse_logging (xmlNodePtr node, void *arg)
{
ice_config_t *config = arg;
int old_trigger_size = -1, old_archive = -1;
struct cfg_tag icecast_tags[] =
{
{ "accesslog", _parse_accesslog, &config->access_log },
{ "errorlog", _parse_errorlog, &config->error_log },
{ "playlistlog", _parse_playlistlog, &config->playlist_log },
{ "accesslog", config_get_str, &config->access_log.name },
{ "accesslog_ip", config_get_bool, &config->access_log.log_ip },
{ "accesslog_exclude_ext",
config_get_str, &config->access_log.exclude_ext },
{ "accesslog_lines",
config_get_int, &config->access_log.display },
{ "errorlog", config_get_str, &config->error_log },
{ "errorlog_lines", config_get_int, &config->error_log.display },
{ "loglevel", config_get_int, &config->error_log.level },
{ "playlistlog", config_get_str, &config->playlist_log },
{ "playlistlog_lines",
config_get_int, &config->playlist_log.display },
{ "logsize", config_get_int, &old_trigger_size },
{ "logarchive", config_get_bool, &old_archive },
{ NULL, NULL, NULL }
};
config->access_log.display = 100;
config->error_log.display = 100;
config->playlist_log.display = 10;
if (parse_xml_tags (node, icecast_tags))
return -1;
if (old_trigger_size > 0)
{
config->error_log.trigger_size = old_trigger_size;
config->access_log.trigger_size = old_trigger_size;
}
if (old_archive > 0)
{
config->error_log.archive = old_archive;
config->access_log.archive = old_archive;
}
return 0;
}

View File

@ -140,6 +140,33 @@ typedef struct
char *password;
} ice_master_details;
typedef struct
{
char *name;
int log_ip;
int archive;
int display;
int trigger_size;
char *exclude_ext;
} access_log;
typedef struct
{
char *name;
int archive;
int display;
int trigger_size;
int level;
} error_log;
typedef struct
{
char *name;
int archive;
int display;
int trigger_size;
} playlist_log;
typedef struct ice_config_tag
{
char *config_filename;
@ -207,17 +234,9 @@ typedef struct ice_config_tag
aliases *aliases;
unsigned slaves_count;
char *access_log;
int access_log_ip;
int access_log_lines;
char *access_log_exclude_ext;
char *error_log;
int error_log_lines;
char *playlist_log;
int playlist_log_lines;
int loglevel;
int logsize;
int logarchive;
access_log access_log;
error_log error_log;
playlist_log playlist_log;
int chroot;
int chuid;

View File

@ -1137,7 +1137,7 @@ static void _handle_stats_request (client_t *client, char *uri)
static void check_for_filtering (ice_config_t *config, client_t *client)
{
const char *uri = httpp_getvar (client->parser, HTTPP_VAR_URI);
char *pattern = config->access_log_exclude_ext;
char *pattern = config->access_log.exclude_ext;
char *extension = strrchr (uri, '.');
if (extension == NULL || uri == NULL || pattern == NULL)

View File

@ -500,7 +500,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
char *eol = strrchr (reference, '.');
if (eol)
*eol = '\0';
stats_get_xml (&doc, 0, reference);
doc = stats_get_xml (0, reference);
free (reference);
admin_send_response (doc, httpclient, XSLT, "xspf.xsl");
xmlFreeDoc(doc);

View File

@ -150,7 +150,7 @@ void logging_access(client_t *client)
user_agent = "-";
config = config_get_config();
if (config->access_log_ip)
if (config->access_log.log_ip)
ip = client->con->ip;
config_release_config ();
#ifdef HAVE_LOG_DIRECT_KEEP
@ -218,37 +218,37 @@ void log_parse_failure (void *ctx, const char *fmt, ...)
void restart_logging (ice_config_t *config)
{
if (strcmp (config->error_log, "-"))
if (strcmp (config->error_log.name, "-"))
{
char fn_error[FILENAME_MAX];
snprintf (fn_error, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->error_log);
snprintf (fn_error, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->error_log.name);
log_set_filename (errorlog, fn_error);
log_set_level (errorlog, config->loglevel);
log_set_trigger (errorlog, config->logsize);
log_set_lines_kept (errorlog, config->error_log_lines);
log_set_archive_timestamp(errorlog, config->logarchive);
log_set_level (errorlog, config->error_log.level);
log_set_trigger (errorlog, config->error_log.trigger_size);
log_set_lines_kept (errorlog, config->error_log.display);
log_set_archive_timestamp(errorlog, config->error_log.archive);
log_reopen (errorlog);
}
if (strcmp (config->access_log, "-"))
if (strcmp (config->access_log.name, "-"))
{
char fn_error[FILENAME_MAX];
snprintf (fn_error, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->access_log);
snprintf (fn_error, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->access_log.name);
log_set_filename (accesslog, fn_error);
log_set_trigger (accesslog, config->logsize);
log_set_lines_kept (accesslog, config->access_log_lines);
log_set_archive_timestamp (accesslog, config->logarchive);
log_set_trigger (accesslog, config->access_log.trigger_size);
log_set_lines_kept (accesslog, config->access_log.display);
log_set_archive_timestamp (accesslog, config->access_log.archive);
log_reopen (accesslog);
}
if (config->playlist_log)
if (config->playlist_log.name)
{
char fn_error[FILENAME_MAX];
snprintf (fn_error, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->playlist_log);
snprintf (fn_error, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->playlist_log.name);
log_set_filename (playlistlog, fn_error);
log_set_trigger (playlistlog, config->logsize);
log_set_lines_kept (playlistlog, config->playlist_log_lines);
log_set_archive_timestamp (playlistlog, config->logarchive);
log_set_trigger (playlistlog, config->playlist_log.trigger_size);
log_set_lines_kept (playlistlog, config->playlist_log.display);
log_set_archive_timestamp (playlistlog, config->playlist_log.archive);
log_reopen (playlistlog);
}
}

View File

@ -207,13 +207,13 @@ static int _start_logging(void)
ice_config_t *config = config_get_config_unlocked();
if(strcmp(config->error_log, "-")) {
snprintf(fn_error, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->error_log);
if(strcmp(config->error_log.name, "-")) {
snprintf(fn_error, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->error_log.name);
errorlog = log_open(fn_error);
log_to_stderr = 0;
if (config->logsize)
log_set_trigger (errorlog, config->logsize);
log_set_archive_timestamp(errorlog, config->logarchive);
if (config->error_log.trigger_size)
log_set_trigger (errorlog, config->error_log.trigger_size);
log_set_archive_timestamp(errorlog, config->error_log.archive);
} else {
errorlog = log_open_file(stderr);
log_to_stderr = 1;
@ -227,15 +227,15 @@ static int _start_logging(void)
strerror(errno));
_fatal_error(buf);
}
log_set_level(errorlog, config->loglevel);
log_set_level(errorlog, config->error_log.level);
if(strcmp(config->access_log, "-")) {
snprintf(fn_access, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->access_log);
if(strcmp(config->access_log.name, "-")) {
snprintf(fn_access, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->access_log.name);
accesslog = log_open(fn_access);
log_to_stderr = 0;
if (config->logsize)
log_set_trigger (accesslog, config->logsize);
log_set_archive_timestamp(accesslog, config->logarchive);
if (config->access_log.trigger_size)
log_set_trigger (accesslog, config->access_log.trigger_size);
log_set_archive_timestamp(accesslog, config->access_log.archive);
} else {
accesslog = log_open_file(stderr);
log_to_stderr = 1;
@ -250,8 +250,8 @@ static int _start_logging(void)
_fatal_error(buf);
}
if(config->playlist_log) {
snprintf(fn_playlist, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->playlist_log);
if(config->playlist_log.name) {
snprintf(fn_playlist, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->playlist_log.name);
playlistlog = log_open(fn_playlist);
if (playlistlog < 0) {
buf[sizeof(buf)-1] = 0;
@ -262,19 +262,19 @@ static int _start_logging(void)
_fatal_error(buf);
}
log_to_stderr = 0;
if (config->logsize)
log_set_trigger (playlistlog, config->logsize);
log_set_archive_timestamp(playlistlog, config->logarchive);
if (config->playlist_log.trigger_size)
log_set_trigger (playlistlog, config->playlist_log.trigger_size);
log_set_archive_timestamp(playlistlog, config->playlist_log.archive);
} else {
playlistlog = -1;
}
log_set_level(errorlog, config->loglevel);
log_set_level(errorlog, config->error_log.level);
log_set_level(accesslog, 4);
log_set_level(playlistlog, 4);
log_set_lines_kept (errorlog, config->error_log_lines);
log_set_lines_kept (accesslog, config->access_log_lines);
log_set_lines_kept (playlistlog, config->playlist_log_lines);
log_set_lines_kept (errorlog, config->error_log.display);
log_set_lines_kept (accesslog, config->access_log.display);
log_set_lines_kept (playlistlog, config->playlist_log.display);
if (errorlog >= 0 && accesslog >= 0) return 1;

View File

@ -59,6 +59,7 @@ typedef struct source_tag
int yp_public;
int shoutcast_compat;
int log_id;
/* per source burst handling for connecting clients */
unsigned int burst_size; /* trigger level for burst on connect */

View File

@ -914,7 +914,7 @@ void stats_transform_xslt(client_t *client, const char *uri)
char *xslpath = util_get_path_from_normalised_uri (uri);
const char *mount = httpp_get_query_param (client->parser, "mount");
stats_get_xml(&doc, STATS_PUBLIC, mount);
doc = stats_get_xml (STATS_PUBLIC, mount);
xslt_transform(doc, xslpath, client);
@ -922,18 +922,19 @@ void stats_transform_xslt(client_t *client, const char *uri)
free (xslpath);
}
void stats_get_xml(xmlDocPtr *doc, int hidden, const char *show_mount)
xmlDocPtr stats_get_xml (int hidden, const char *show_mount)
{
xmlDocPtr doc;
xmlNodePtr node;
*doc = xmlNewDoc (XMLSTR("1.0"));
node = xmlNewDocNode (*doc, NULL, XMLSTR("icestats"), NULL);
xmlDocSetRootElement(*doc, node);
doc = xmlNewDoc (XMLSTR("1.0"));
node = xmlNewDocNode (doc, NULL, XMLSTR("icestats"), NULL);
xmlDocSetRootElement(doc, node);
node = _dump_stats_to_doc (node, show_mount, hidden);
if (show_mount && node)
{
{
source_t *source;
/* show each listener */
avl_tree_rlock (global.source_tree);
@ -944,6 +945,7 @@ void stats_get_xml(xmlDocPtr *doc, int hidden, const char *show_mount)
avl_tree_unlock (global.source_tree);
}
return doc;
}
static int _compare_stats(void *arg, void *a, void *b)
@ -1008,7 +1010,7 @@ refbuf_t *stats_get_streams (int prepend)
int ret;
stats_source_t *source = (stats_source_t *)node->key;
if (source->hidden == 0)
if (source->hidden & STATS_SLAVE)
{
if (remaining <= strlen (source->source) + prelen + 3)
{

View File

@ -53,7 +53,7 @@ void stats_global_calc(void);
void stats_transform_xslt(client_t *client, const char *uri);
void stats_sendxml(client_t *client);
void stats_get_xml(xmlDocPtr *doc, int show_hidden, const char *show_mount);
xmlDocPtr stats_get_xml(int show_hidden, const char *show_mount);
char *stats_get_value(const char *source, const char *name);
#endif /* __STATS_H__ */

View File

@ -545,7 +545,7 @@ void StartStats(void *dummy)
xmlDocPtr doc;
stats_get_xml(&doc, 0, NULL);
doc = stats_get_xml(0, NULL);
xmlNodePtr cur;
cur = xmlDocGetRootElement(doc);

View File

@ -3,7 +3,7 @@
[Setup]
AppName=Icecast2-KH
AppVerName=Icecast v2.3.2-kh2
AppVerName=Icecast v2.3.2-kh3
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.2-kh2_setup
OutputBaseFilename=icecast2_win32_v2.3.2-kh3_setup
WizardImageFile=icecast2logo2.bmp
WizardImageStretch=no
; uncomment the following line if you want your installation to run on NT 3.51 too.