Commit 1773e723 authored by Philipp Schafft's avatar Philipp Schafft

Merge branch 'ph3-devel-module-links'

parents 3f224609 bfcac5d3
Pipeline #289 failed with stage
in 12 seconds
......@@ -14,6 +14,11 @@
<ul>
<li class="on"><a href="/admin/stats.xsl">Administration</a></li>
<li><a href="/admin/listmounts.xsl">Mountpoint list</a></li>
<xsl:for-each select="(/report/extension/icestats | /icestats | /iceresponse)/modules/module">
<xsl:if test="@management-url and @management-title">
<li><a href="{@management-url}"><xsl:value-of select="@management-title" /></a></li>
</xsl:if>
</xsl:for-each>
<li><a href="/status.xsl">Public area</a></li>
</ul>
</div>
......
......@@ -317,6 +317,17 @@ int admin_command_table_unregister(const char *prefix)
return -1;
}
/* build an XML root node including some common tags */
xmlNodePtr admin_build_rootnode(xmlDocPtr doc, const char *name)
{
xmlNodePtr rootnode = xmlNewDocNode(doc, NULL, XMLSTR(name), NULL);
xmlNodePtr modules = module_container_get_modulelist_as_xml(global.modulecontainer);
xmlAddChild(rootnode, modules);
return rootnode;
}
/* build an XML doc containing information about currently running sources.
* If a mountpoint is passed then that source will not be added to the XML
* doc even if the source is running */
......@@ -330,7 +341,7 @@ xmlDocPtr admin_build_sourcelist(const char *mount)
time_t now = time(NULL);
doc = xmlNewDoc (XMLSTR("1.0"));
xmlnode = xmlNewDocNode (doc, NULL, XMLSTR("icestats"), NULL);
xmlnode = admin_build_rootnode(doc, "icestats");
xmlDocSetRootElement(doc, xmlnode);
if (mount) {
......@@ -649,7 +660,7 @@ static void command_move_clients(client_t *client,
ICECAST_LOG_INFO("source is \"%s\", destination is \"%s\"", source->mount, dest->mount);
doc = xmlNewDoc(XMLSTR("1.0"));
node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL);
node = admin_build_rootnode(doc, "iceresponse");
xmlDocSetRootElement(doc, node);
source_move_clients(source, dest);
......@@ -744,7 +755,7 @@ static void command_show_listeners(client_t *client,
char buf[22];
doc = xmlNewDoc(XMLSTR("1.0"));
node = xmlNewDocNode(doc, NULL, XMLSTR("icestats"), NULL);
node = admin_build_rootnode(doc, "icestats");
srcnode = xmlNewChild(node, NULL, XMLSTR("source"), NULL);
xmlSetProp(srcnode, XMLSTR("mount"), XMLSTR(source->mount));
xmlDocSetRootElement(doc, node);
......@@ -902,12 +913,12 @@ static void command_manageauth(client_t *client, source_t *source, admin_format_
}
doc = xmlNewDoc(XMLSTR("1.0"));
node = xmlNewDocNode(doc, NULL, XMLSTR("icestats"), NULL);
node = admin_build_rootnode(doc, "icestats");
rolenode = admin_add_role_to_authentication(auth, node);
if (message) {
msgnode = xmlNewChild(node, NULL, XMLSTR("iceresponse"), NULL);
msgnode = admin_build_rootnode(doc, "iceresponse");
xmlNewTextChild(msgnode, NULL, XMLSTR("message"), XMLSTR(message));
}
......@@ -941,7 +952,7 @@ static void command_kill_source(client_t *client,
xmlNodePtr node;
doc = xmlNewDoc (XMLSTR("1.0"));
node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL);
node = admin_build_rootnode(doc, "iceresponse");
xmlNewTextChild(node, NULL, XMLSTR("message"), XMLSTR("Source Removed"));
xmlNewTextChild(node, NULL, XMLSTR("return"), XMLSTR("1"));
xmlDocSetRootElement(doc, node);
......@@ -971,7 +982,7 @@ static void command_kill_client(client_t *client,
listener = source_find_client(source, id);
doc = xmlNewDoc(XMLSTR("1.0"));
node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL);
node = admin_build_rootnode(doc, "iceresponse");
xmlDocSetRootElement(doc, node);
ICECAST_LOG_DEBUG("Response is %d", response);
......@@ -1028,7 +1039,7 @@ static void command_metadata(client_t *client,
int same_ip = 1;
doc = xmlNewDoc(XMLSTR("1.0"));
node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL);
node = admin_build_rootnode(doc, "iceresponse");
xmlDocSetRootElement(doc, node);
ICECAST_LOG_DEBUG("Got metadata update request");
......@@ -1155,7 +1166,7 @@ static void command_queue_reload(client_t *client, source_t *source, admin_forma
global_unlock();
doc = xmlNewDoc (XMLSTR("1.0"));
node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL);
node = admin_build_rootnode(doc, "iceresponse");
xmlNewTextChild(node, NULL, XMLSTR("message"), XMLSTR("Config reload queued"));
xmlNewTextChild(node, NULL, XMLSTR("return"), XMLSTR("1"));
xmlDocSetRootElement(doc, node);
......@@ -1207,7 +1218,7 @@ static void command_updatemetadata(client_t *client,
xmlNodePtr node, srcnode;
doc = xmlNewDoc(XMLSTR("1.0"));
node = xmlNewDocNode(doc, NULL, XMLSTR("icestats"), NULL);
node = admin_build_rootnode(doc, "icestats");
srcnode = xmlNewChild(node, NULL, XMLSTR("source"), NULL);
xmlSetProp(srcnode, XMLSTR("mount"), XMLSTR(source->mount));
xmlDocSetRootElement(doc, node);
......
......@@ -21,6 +21,8 @@
#include "compat.h"
#include "resourcematch.h"
#define ADMIN_ICESTATS_LEGACY_EXTENSION_APPLICATION "http://icecast.org/specs/legacy-icestats"
/* types */
#define ADMINTYPE_ERROR (-1)
#define ADMINTYPE_GENERAL 1
......
......@@ -24,6 +24,8 @@
#include <stdlib.h>
#include <string.h>
#include <libxml/tree.h>
#include "common/thread/thread.h"
#include "common/avl/avl.h"
#include "common/httpp/httpp.h"
......@@ -51,7 +53,7 @@
#include "listensocket.h"
#include "fastevent.h"
/* for ADMIN_COMMAND_ERROR */
/* for ADMIN_COMMAND_ERROR, and ADMIN_ICESTATS_LEGACY_EXTENSION_APPLICATION */
#include "admin.h"
#ifdef _WIN32
......@@ -301,7 +303,6 @@ int client_read_bytes(client_t *client, void *buf, unsigned len)
static inline void _client_send_error(client_t *client, const icecast_error_t *error)
{
ice_config_t *config;
reportxml_t *report;
admin_format_t admin_format;
const char *xslt = NULL;
......@@ -323,28 +324,8 @@ static inline void _client_send_error(client_t *client, const icecast_error_t *e
break;
}
config = config_get_config();
report = reportxml_database_build_report(config->reportxml_db, error->uuid, -1);
config_release_config();
if (!report) {
reportxml_node_t *root, *incident, *state, *text;
report = reportxml_new();
root = reportxml_get_root_node(report);
incident = reportxml_node_new(REPORTXML_NODE_TYPE_INCIDENT, NULL, NULL, NULL);
state = reportxml_node_new(REPORTXML_NODE_TYPE_STATE, NULL, error->uuid, NULL);
text = reportxml_node_new(REPORTXML_NODE_TYPE_TEXT, NULL, NULL, NULL);
reportxml_node_set_content(text, error->message);
reportxml_node_add_child(state, text);
reportxml_node_add_child(incident, state);
reportxml_node_add_child(root, incident);
refobject_unref(text);
refobject_unref(state);
refobject_unref(incident);
refobject_unref(root);
}
report = client_get_reportxml(error->uuid, NULL, error->message);
client_send_reportxml(client, report, DOCUMENT_DOMAIN_ADMIN, xslt, admin_format, error->http_status);
......@@ -623,6 +604,72 @@ void client_send_reportxml(client_t *client, reportxml_t *report, document_domai
xmlFreeDoc(doc);
}
static void client_get_reportxml__add_basic_stats(reportxml_t *report)
{
reportxml_node_t *rootnode, *extension;
xmlNodePtr xmlroot;
xmlNodePtr modules;
rootnode = reportxml_get_root_node(report);
extension = reportxml_node_new(REPORTXML_NODE_TYPE_EXTENSION, NULL, NULL, NULL);
reportxml_node_set_attribute(extension, "application", ADMIN_ICESTATS_LEGACY_EXTENSION_APPLICATION);
reportxml_node_add_child(rootnode, extension);
refobject_unref(rootnode);
xmlroot = xmlNewNode(NULL, XMLSTR("icestats"));
modules = module_container_get_modulelist_as_xml(global.modulecontainer);
xmlAddChild(xmlroot, modules);
reportxml_node_add_xml_child(extension, xmlroot);
refobject_unref(extension);
xmlFreeNode(xmlroot);
}
reportxml_t *client_get_reportxml(const char *state_definition, const char *state_akindof, const char *state_text)
{
reportxml_t *report = NULL;
if (state_definition) {
ice_config_t *config;
config = config_get_config();
report = reportxml_database_build_report(config->reportxml_db, state_definition, -1);
config_release_config();
}
if (!report) {
reportxml_node_t *rootnode, *incidentnode, *statenode;
report = reportxml_new();
rootnode = reportxml_get_root_node(report);
incidentnode = reportxml_node_new(REPORTXML_NODE_TYPE_INCIDENT, NULL, NULL, NULL);
statenode = reportxml_node_new(REPORTXML_NODE_TYPE_STATE, NULL, state_definition, state_akindof);
if (state_text) {
reportxml_node_t *textnode;
textnode = reportxml_node_new(REPORTXML_NODE_TYPE_TEXT, NULL, NULL, NULL);
reportxml_node_set_content(textnode, state_text);
reportxml_node_add_child(statenode, textnode);
refobject_unref(textnode);
}
reportxml_node_add_child(incidentnode, statenode);
reportxml_node_add_child(rootnode, incidentnode);
refobject_unref(statenode);
refobject_unref(incidentnode);
refobject_unref(rootnode);
}
client_get_reportxml__add_basic_stats(report);
return report;
}
admin_format_t client_get_admin_format_by_content_negotiation(client_t *client)
{
const char *pref;
......
......@@ -144,6 +144,7 @@ void client_send_101(client_t *client, reuse_t reuse);
void client_send_204(client_t *client);
void client_send_426(client_t *client, reuse_t reuse);
void client_send_reportxml(client_t *client, reportxml_t *report, document_domain_t domain, const char *xsl, admin_format_t admin_format_hint, int status);
reportxml_t *client_get_reportxml(const char *state_definition, const char *state_akindof, const char *state_text);
admin_format_t client_get_admin_format_by_content_negotiation(client_t *client);
int client_send_bytes (client_t *client, const void *buf, unsigned len);
int client_read_bytes (client_t *client, void *buf, unsigned len);
......
......@@ -18,6 +18,7 @@
#include "refobject.h"
#include "module.h"
#include "cfgfile.h" /* for XMLSTR() */
struct module_tag {
refobject_base_t __base;
......@@ -26,6 +27,8 @@ struct module_tag {
size_t client_handlers_len;
module_setup_handler_t freecb;
void *userdata;
char *management_link_url;
char *management_link_title;
};
......@@ -118,6 +121,37 @@ module_t * module_container_get_module(module_container_t *self, co
return ret;
}
xmlNodePtr module_container_get_modulelist_as_xml(module_container_t *self)
{
xmlNodePtr root;
avl_node *avlnode;
if (!self)
return NULL;
root = xmlNewNode(NULL, XMLSTR("modules"));
if (!root)
return NULL;
thread_mutex_lock(&(self->lock));
avlnode = avl_get_first(self->module);
while (avlnode) {
module_t *module = avlnode->key;
xmlNodePtr node = xmlNewChild(root, NULL, XMLSTR("module"), NULL);
xmlSetProp(node, XMLSTR("name"), XMLSTR(refobject_get_name(module)));
if (module->management_link_url)
xmlSetProp(node, XMLSTR("management-url"), XMLSTR(module->management_link_url));
if (module->management_link_title)
xmlSetProp(node, XMLSTR("management-title"), XMLSTR(module->management_link_title));
avlnode = avl_get_next(avlnode);
}
thread_mutex_unlock(&(self->lock));
return root;
}
static void __module_free(refobject_t self, void **userdata)
{
module_t *mod = REFOBJECT_TO_TYPE(self, module_t *);
......@@ -128,6 +162,9 @@ static void __module_free(refobject_t self, void **userdata)
if (mod->userdata)
free(mod->userdata);
free(mod->management_link_url);
free(mod->management_link_title);
thread_mutex_destroy(&(mod->lock));
}
......@@ -153,6 +190,42 @@ module_t * module_new(const char *name, module_setup_handler_t newc
return ret;
}
int module_add_link(module_t *self, const char *type, const char *url, const char *title)
{
char *n_url = NULL;
char *n_title = NULL;
if (!self || !type)
return -1;
if (strcmp(type, "management-url") != 0)
return -1;
if (url) {
n_url = strdup(url);
if (!n_url)
return -1;
}
if (title) {
n_title = strdup(title);
if (!n_title) {
free(n_url);
return -1;
}
}
thread_mutex_lock(&(self->lock));
free(self->management_link_url);
free(self->management_link_title);
self->management_link_url = n_url;
self->management_link_title = n_title;
thread_mutex_unlock(&(self->lock));
return 0;
}
const module_client_handler_t * module_get_client_handler(module_t *self, const char *name)
{
size_t i;
......
......@@ -9,6 +9,8 @@
#ifndef __MODULE_H__
#define __MODULE_H__
#include <libxml/tree.h>
#include "icecasttypes.h"
typedef void (*module_client_handler_function_t)(module_t *self, client_t *client, const char *uri);
......@@ -23,9 +25,12 @@ module_container_t * module_container_new(void);
int module_container_add_module(module_container_t *self, module_t *module);
int module_container_delete_module(module_container_t *self, const char *name);
module_t * module_container_get_module(module_container_t *self, const char *name);
xmlNodePtr module_container_get_modulelist_as_xml(module_container_t *self);
module_t * module_new(const char *name, module_setup_handler_t newcb, module_setup_handler_t freecb, void *userdata);
int module_add_link(module_t *self, const char *type, const char *url, const char *title);
/* Note: Those functions are not really thread safe as (module_client_handler_t) is not thread safe. This is by design. */
const module_client_handler_t * module_get_client_handler(module_t *self, const char *name);
int module_add_client_handler(module_t *self, const module_client_handler_t *handlers, size_t len);
......
......@@ -286,6 +286,14 @@ reportxml_node_t * reportxml_get_node_by_attribute(reportxml_t *report, con
return reportxml_node_get_child_by_attribute(report->root, key, value, include_definitions);
}
reportxml_node_t * reportxml_get_node_by_type(reportxml_t *report, reportxml_node_type_t type, int include_definitions)
{
if (!report)
return NULL;
return reportxml_node_get_child_by_type(report->root, type, include_definitions);
}
reportxml_t * reportxml_parse_xmldoc(xmlDocPtr doc)
{
reportxml_node_t *root;
......@@ -822,6 +830,33 @@ reportxml_node_t * reportxml_node_get_child_by_attribute(reportxml_node_t *
return NULL;
}
reportxml_node_t * reportxml_node_get_child_by_type(reportxml_node_t *node, reportxml_node_type_t type, int include_definitions)
{
size_t i;
if (!node)
return NULL;
if (node->type == type) {
if (refobject_ref(node) != 0)
return NULL;
return node;
}
if (node->type == REPORTXML_NODE_TYPE_DEFINITION && !include_definitions)
return NULL;
for (i = 0; i < node->childs_len; i++) {
reportxml_node_t *ret;
ret = reportxml_node_get_child_by_type(node->childs[i], type, include_definitions);
if (ret != NULL)
return ret;
}
return NULL;
}
int reportxml_node_set_content(reportxml_node_t *node, const char *value)
{
const struct nodedef *nodedef;
......
......@@ -77,6 +77,8 @@ reportxml_node_t * reportxml_get_root_node(reportxml_t *report);
* <definition>s are skipped.
*/
reportxml_node_t * reportxml_get_node_by_attribute(reportxml_t *report, const char *key, const char *value, int include_definitions);
/* This gets a node by it's type. Otherwise identical to reportxml_get_node_by_attribute() */
reportxml_node_t * reportxml_get_node_by_type(reportxml_t *report, reportxml_node_type_t type, int include_definitions);
/* This function parses an XML document and returns the parst report XML document */
reportxml_t * reportxml_parse_xmldoc(xmlDocPtr doc);
/* This function renders an report XML document as XML structure */
......@@ -108,6 +110,8 @@ ssize_t reportxml_node_count_child(reportxml_node_t *node);
reportxml_node_t * reportxml_node_get_child(reportxml_node_t *node, size_t idx);
/* This gets an child by it's value of the given attribute. See reportxml_get_node_by_attribute() for more details. */
reportxml_node_t * reportxml_node_get_child_by_attribute(reportxml_node_t *node, const char *key, const char *value, int include_definitions);
/* This gets a child by it's type. Otherwise identical to reportxml_node_get_child_by_attribute() */
reportxml_node_t * reportxml_node_get_child_by_type(reportxml_node_t *node, reportxml_node_type_t type, int include_definitions);
/* This gets and sets the text content of an node (used for <text>) */
int reportxml_node_set_content(reportxml_node_t *node, const char *value);
char * reportxml_node_get_content(reportxml_node_t *node);
......
......@@ -1063,12 +1063,16 @@ xmlDocPtr stats_get_xml(int show_hidden, const char *show_mount, client_t *clien
{
xmlDocPtr doc;
xmlNodePtr node;
xmlNodePtr modules;
source_t * source;
doc = xmlNewDoc (XMLSTR("1.0"));
node = xmlNewDocNode (doc, NULL, XMLSTR("icestats"), NULL);
xmlDocSetRootElement(doc, node);
modules = module_container_get_modulelist_as_xml(global.modulecontainer);
xmlAddChild(node, modules);
node = _dump_stats_to_doc(node, show_mount, show_hidden, client);
if (show_mount && node) {
......
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